[
  {
    "path": ".github/dependabot.yml",
    "content": "# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates\nversion: 2\nupdates:\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\" # Location of package manifests\n    schedule:\n      interval: \"weekly\"\n"
  },
  {
    "path": ".github/workflows/CompatHelper.yml",
    "content": "name: CompatHelper\non:\n  schedule:\n    - cron: 0 0 * * *\n  workflow_dispatch:\npermissions:\n  contents: write\n  pull-requests: write\njobs:\n  CompatHelper:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Check if Julia is already available in the PATH\n        id: julia_in_path\n        run: which julia\n        continue-on-error: true\n      - name: Install Julia, but only if it is not already available in the PATH\n        uses: julia-actions/setup-julia@v2\n        with:\n          version: '1'\n          arch: ${{ runner.arch }}\n        if: steps.julia_in_path.outcome != 'success'\n      - name: \"Add the General registry via Git\"\n        run: |\n          import Pkg\n          ENV[\"JULIA_PKG_SERVER\"] = \"\"\n          Pkg.Registry.add(\"General\")\n        shell: julia --color=yes {0}\n      - name: \"Install CompatHelper\"\n        run: |\n          import Pkg\n          name = \"CompatHelper\"\n          uuid = \"aa819f21-2bde-4658-8897-bab36330d9b7\"\n          version = \"3\"\n          Pkg.add(; name, uuid, version)\n        shell: julia --color=yes {0}\n      - name: \"Run CompatHelper\"\n        run: |\n          import CompatHelper\n          CompatHelper.main()\n        shell: julia --color=yes {0}\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          COMPATHELPER_PRIV: ${{ secrets.DOCUMENTER_KEY }}\n          # COMPATHELPER_PRIV: ${{ secrets.COMPATHELPER_PRIV }}\n"
  },
  {
    "path": ".github/workflows/TagBot.yml",
    "content": "name: TagBot\non:\n  issue_comment:\n    types:\n      - created\n  workflow_dispatch:\njobs:\n  TagBot:\n    if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot'\n    runs-on: ubuntu-latest\n    steps:\n      - uses: JuliaRegistries/TagBot@v1\n        with:\n          token: ${{ secrets.GITHUB_TOKEN }}\n          ssh: ${{ secrets.TAGBOT }}\n"
  },
  {
    "path": ".github/workflows/UnitTest.yml",
    "content": "name: Unit test\n\non:\n  push:\n    tags:\n      - 'v*'\n    branches:\n      - master\n    paths-ignore:\n      - 'LICENSE.md'\n      - 'README.md'\n      - '.github/workflows/TagBot.yml'\n  pull_request:\n    paths-ignore:\n      - 'LICENSE.md'\n      - 'README.md'\n      - '.github/workflows/TagBot.yml'\n  schedule:\n    - cron: '20 00 1 * *'\n\nconcurrency:\n  group: build-${{ github.event.pull_request.number || github.ref }}-${{ github.workflow }}\n  cancel-in-progress: true\n\njobs:\n  test:\n    runs-on: ${{ matrix.os }}\n    strategy:\n      # allow-failure is not supported yet\n      # https://github.com/actions/toolkit/issues/399\n      fail-fast: false\n      matrix:\n        julia-version: ['1.0', 'lts', '1', 'pre']\n        os: [ubuntu-latest, windows-latest, macOS-latest]\n        julia-arch: [x64]\n        # only test one 32-bit job\n        include:\n          - os: ubuntu-latest\n            julia-version: '1'\n            julia-arch: x86\n\n    steps:\n      - uses: actions/checkout@v6\n      - uses: julia-actions/setup-julia@v2\n        with:\n          version: ${{ matrix.julia-version }}\n          arch: ${{ matrix.julia-arch }}\n      - uses: julia-actions/cache@v3\n      - name: \"Unit Test\"\n        uses: julia-actions/julia-runtest@v1\n      - uses: julia-actions/julia-processcoverage@v1\n      - uses: codecov/codecov-action@v6\n        with:\n          token: ${{ secrets.CODECOV_TOKEN }}\n          files: lcov.info\n"
  },
  {
    "path": ".github/workflows/docs.yml",
    "content": "name: Documentation\n\non:\n  pull_request:\n  push:\n    branches:\n      - 'master'\n      - 'release-'\n    tags: '*'\n  release:\n    types: [published]\n\njobs:\n  build:\n    runs-on: ${{ matrix.os }}\n    strategy:\n      matrix:\n        julia-version: [1]\n        os: [ubuntu-latest]\n    steps:\n      - uses: actions/checkout@v6\n      - uses: julia-actions/setup-julia@latest\n        with:\n          version: ${{ matrix.julia-version }}\n      - name: Cache artifacts\n        uses: actions/cache@v5\n        env:\n          cache-name: cache-artifacts\n        with:\n          path: ~/.julia/artifacts\n          key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }}\n          restore-keys: |\n            ${{ runner.os }}-test-${{ env.cache-name }}-\n            ${{ runner.os }}-test-\n            ${{ runner.os }}-\n      - name: Install dependencies\n        run: julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()'\n      - name: Build and deploy\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n        run: julia --project=docs/ docs/make.jl\n"
  },
  {
    "path": ".github/workflows/invalidations.yml",
    "content": "name: Invalidations\non: pull_request\n\njobs:\n  evaluate:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: julia-actions/setup-julia@v2\n      with:\n        version: '1.10'\n    - uses: actions/checkout@v6\n    - uses: julia-actions/julia-buildpkg@latest\n    - uses: julia-actions/julia-invalidations@v1\n      id: invs_pr\n\n    - uses: actions/checkout@v6\n      with:\n        ref: 'master'\n    - uses: julia-actions/julia-buildpkg@latest\n    - uses: julia-actions/julia-invalidations@v1\n      id: invs_master\n\n    - name: Report invalidation counts\n      run: |\n        echo \"Invalidations on master: ${{ steps.invs_master.outputs.total }} (${{ steps.invs_master.outputs.deps }} via deps)\"\n        echo \"This branch: ${{ steps.invs_pr.outputs.total }} (${{ steps.invs_pr.outputs.deps }} via deps)\"\n      shell: bash\n    - name: PR doesn't increase number of invalidations\n      run: |\n        if (( ${{ steps.invs_pr.outputs.total }} > ${{ steps.invs_master.outputs.total }} )); then\n            exit 1\n        fi\n      shell: bash\n"
  },
  {
    "path": ".gitignore",
    "content": "Manifest.toml\nManifest-v*.*.toml\ndocs/build\nLocalPreferences.toml\n.vscode\n"
  },
  {
    "path": "LICENSE.md",
    "content": "The FArrayMod.jl package is licensed under the MIT \"Expat\" License:\n\n> Copyright (c) 2014:\n>  * Alexander Samoilov\n>\n> Permission is hereby granted, free of charge, to any person obtaining\n> a copy of this software and associated documentation files (the\n> \"Software\"), to deal in the Software without restriction, including\n> without limitation the rights to use, copy, modify, merge, publish,\n> distribute, sublicense, and/or sell copies of the Software, and to\n> permit persons to whom the Software is furnished to do so, subject to\n> the following conditions:\n>\n> The above copyright notice and this permission notice shall be\n> included in all copies or substantial portions of the Software.\n>\n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n> IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n> CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n> TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n> SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "Project.toml",
    "content": "name = \"OffsetArrays\"\nuuid = \"6fe1bfb0-de20-5000-8ca7-80f57d26f881\"\nversion = \"1.17.0\"\n\n[deps]\nAdapt = \"79e6a3ab-5dfb-504d-930d-738a2a938a0e\"\n\n[weakdeps]\nAdapt = \"79e6a3ab-5dfb-504d-930d-738a2a938a0e\"\n\n[extensions]\nOffsetArraysAdaptExt = \"Adapt\"\n\n[compat]\nAdapt = \"2, 3, 4\"\nAqua = \"0.8\"\nCatIndices = \"0.2\"\nDelimitedFiles = \"<0.0.1, 1\"\nDistributedArrays = \"0.6\"\nDocumenter = \"0.27, 1\"\nEllipsisNotation = \"1\"\nFillArrays = \"0.11, 0.13, 1\"\nLinearAlgebra = \"<0.0.1, 1\"\nStaticArrays = \"1\"\nTest = \"<0.0.1, 1\"\njulia = \"0.7, 1\"\n\n[extras]\nAdapt = \"79e6a3ab-5dfb-504d-930d-738a2a938a0e\"\nAqua = \"4c88cf16-eb10-579e-8560-4a9242c79595\"\nCatIndices = \"aafaddc9-749c-510e-ac4f-586e18779b91\"\nDelimitedFiles = \"8bb1440f-4735-579b-a4ab-409b98df4dab\"\nDistributedArrays = \"aaf54ef3-cdf8-58ed-94cc-d582ad619b94\"\nDocumenter = \"e30172f5-a6a5-5a46-863b-614d45cd2de4\"\nEllipsisNotation = \"da5c29d0-fa7d-589e-88eb-ea29b0a81949\"\nFillArrays = \"1a297f60-69ca-5386-bcde-b61e274b549b\"\nLinearAlgebra = \"37e2e46d-f89d-539d-b4ee-838fcccc9c8e\"\nStaticArrays = \"90137ffa-7385-5640-81b9-e52037218182\"\nTest = \"8dfed614-e22c-5e08-85e1-65c5234f0b40\"\n\n[targets]\ntest = [\"Adapt\", \"Aqua\", \"CatIndices\", \"DistributedArrays\", \"DelimitedFiles\", \"Documenter\", \"EllipsisNotation\", \"FillArrays\", \"LinearAlgebra\", \"StaticArrays\", \"Test\"]\n"
  },
  {
    "path": "README.md",
    "content": "# OffsetArrays.jl\n\n| Documentation |  Build Status | Code coverage | Version |\n| :-: | :-: | :-: | :-: |\n| [![][docs-stable-img]][docs-stable-url] |  [![][action-img]][action-url] | [![][codecov-img]][codecov-url] | [![][ver-img]][ver-url]  |\n| [![][docs-dev-img]][docs-dev-url]  |  [![][pkgeval-img]][pkgeval-url] | | [![][deps-img]][deps-url] |\n\n## Introduction\n\nOffsetArrays provides Julia users with arrays that have arbitrary\nindices, similar to those found in some other programming languages\nlike Fortran.\n\nAn `OffsetArray` is a lightweight wrapper around an `AbstractArray` that shifts its indices.\nGenerally, indexing into an `OffsetArray` should be as performant as the parent array.\n\n## Usage\n\nThere are two ways to construct `OffsetArray`s: by specifying the axes of the array, or\nby specifying its origin.\n\nThe first way to construct an `OffsetArray` by specifying its axes is:\n\n```julia\nOA = OffsetArray(A, axis1, axis2, ...)\n```\n\nwhere you want `OA` to have axes `(axis1, axis2, ...)` and be indexed by values that\nfall within these axis ranges. Example:\n\n```julia\njulia> using OffsetArrays\n\njulia> A = Float64.(reshape(1:15, 3, 5))\n3×5 Matrix{Float64}:\n 1.0  4.0  7.0  10.0  13.0\n 2.0  5.0  8.0  11.0  14.0\n 3.0  6.0  9.0  12.0  15.0\n\njulia> axes(A) # indices of a Matrix start from 1 along each axis\n(Base.OneTo(3), Base.OneTo(5))\n\njulia> OA = OffsetArray(A, -1:1, 0:4) # OA will have the axes (-1:1, 0:4)\n3×5 OffsetArray(::Matrix{Float64}, -1:1, 0:4) with eltype Float64 with indices -1:1×0:4:\n 1.0  4.0  7.0  10.0  13.0\n 2.0  5.0  8.0  11.0  14.0\n 3.0  6.0  9.0  12.0  15.0\n\njulia> OA[-1, 0]\n1.0\n\njulia> OA[1, 4]\n15.0\n```\n\nThe second way to construct an `OffsetArray` is by specifying the origin, that is, the first index\nalong each axis. This is particularly useful if one wants, eg., arrays that are 0-indexed as opposed\nto 1-indexed.\n\nA convenient way to construct an `OffsetArray` this way is by using `OffsetArrays.Origin`:\n\n```julia\njulia> using OffsetArrays: Origin\n\njulia> Origin(0)(A) # indices begin at 0 along all axes\n3×5 OffsetArray(::Matrix{Float64}, 0:2, 0:4) with eltype Float64 with indices 0:2×0:4:\n 1.0  4.0  7.0  10.0  13.0\n 2.0  5.0  8.0  11.0  14.0\n 3.0  6.0  9.0  12.0  15.0\n\njulia> Origin(2, 3)(A) # indices begin at 2 along the first axis and 3 along the second\n3×5 OffsetArray(::Matrix{Float64}, 2:4, 3:7) with eltype Float64 with indices 2:4×3:7:\n 1.0  4.0  7.0  10.0  13.0\n 2.0  5.0  8.0  11.0  14.0\n 3.0  6.0  9.0  12.0  15.0\n```\n\nWhile the examples here refer to the common case where the parent arrays have indices starting at 1,\nthis is not necessary. An `OffsetArray` may wrap any array that has integer indices, irrespective of\nwhere the indices begin.\n\n## How to go back to 1-indexed arrays\n\nCertain libraries, such as `LinearAlgebra`, require arrays to be indexed from 1. Passing an `OffsetArray`\nwith shifted indices would lead to an error here.\n\n```julia\njulia> A = Float64.(reshape(1:16, 4, 4));\n\njulia> AO = Origin(0)(A);\n\njulia> using LinearAlgebra\n\njulia> Diagonal(AO)\nERROR: ArgumentError: offset arrays are not supported but got an array with index other than 1\n```\n\nThe way to obtain a `1`-indexed array from an `OffsetArray` is by using `OffsetArrays.no_offset_view`.\n\nAn example of this is:\n\n```julia\njulia> OffsetArrays.no_offset_view(AO)\n4×4 Matrix{Float64}:\n 1.0  5.0   9.0  13.0\n 2.0  6.0  10.0  14.0\n 3.0  7.0  11.0  15.0\n 4.0  8.0  12.0  16.0\n```\n\nThis may now be passed to `LinearAlgebra`:\n\n```julia\njulia> D = Diagonal(OffsetArrays.no_offset_view(AO))\n4×4 Diagonal{Float64, Vector{Float64}}:\n 1.0   ⋅     ⋅     ⋅\n  ⋅   6.0    ⋅     ⋅\n  ⋅    ⋅   11.0    ⋅\n  ⋅    ⋅     ⋅   16.0\n```\n\nIf we want to restore the original indices of `AO`, we may wrap an `OffsetArray` around the `Diagonal` as:\n\n```julia\njulia> Origin(AO)(D)\n4×4 OffsetArray(::Diagonal{Float64, Vector{Float64}}, 0:3, 0:3) with eltype Float64 with indices 0:3×0:3:\n 1.0   ⋅     ⋅     ⋅\n  ⋅   6.0    ⋅     ⋅\n  ⋅    ⋅   11.0    ⋅\n  ⋅    ⋅     ⋅   16.0\n```\n\nHere, `Origin(AO)` is able to automatically infer and use the indices of `AO`.\n\n## Best practice on adopting OffsetArrays\n\nFor some applications, OffsetArrays give users an easy-to-understand interface. However, handling\nthe non-conventional axes of OffsetArrays requires extra care. Otherwise, the code might\nerror, crash, or return incorrect results. You can read [the Julialang documentation on\noffset](https://docs.julialang.org/en/v1/devdocs/offset-arrays/) for more information. Here\nwe briefly summarize some of the best practices for users and package authors.\n\n### There is no need to support OffsetArrays for every function\n\nYou don't need to support offset arrays for _internal functions_ that only consume standard 1-based\narrays -- it doesn't change or improve anything.\n\nYou don't need to support offset arrays for functions that _have no well-defined behavior on custom\naxes_. For instance, many linear algebra functions such as matrix multiplication `A * B` does not\nhave an agreed behavior for offset arrays. In this case, it is a better practice to let users do the\nconversion.\n\nThe helper function `Base.require_one_based_indexing` can be used to early check the axes and throw\na meaningful error. If your interface functions do not intend to support offset arrays, we recommend\nyou add this check before starting the real computation.\n\n### use `axes` instead of `size`/`length`\n\nMany implementations assume the array axes start at 1 by writing loops such as `for i in\n1:length(x)` or `for i in 1:size(x, 1)`. A better practice is to use `for i in eachindex(x)` or `for\ni in axes(x, 1)` -- `axes` provides more information than `size` with no performance overhead.\n\nAlso, if you know what indices type you want to use, [`LinearIndices`][doc_LinearIndices] and\n[`CartesianIndices`][doc_CartesianIndices] allow you to loop multidimensional arrays efficiently\nwithout worrying about the axes.\n\n### test against OffsetArrays\n\nFor package authors that declare support for `AbstractArray`, we recommend having a few test cases\nagainst `OffsetArray` to ensure the function works well for arrays with custom axes. This gives you\nmore confidence that users don't run into strange situations.\n\nFor package users that want to use offset arrays, many numerical correctness issues come from the\nfact that `@inbounds` is used inappropriately with the 1-based indexing assumption. Thus for debug\npurposes, it is not a bad idea to start Julia with `--check-bounds=yes`, which turns all `@inbounds`\ninto a no-op and uncover potential out-of-bound errors.\n\n<!-- badges -->\n\n[pkgeval-img]: https://juliaci.github.io/NanosoldierReports/pkgeval_badges/O/OffsetArrays.svg\n[pkgeval-url]: https://juliaci.github.io/NanosoldierReports/pkgeval_badges/report.html\n\n[action-img]: https://github.com/JuliaArrays/OffsetArrays.jl/workflows/Unit%20test/badge.svg\n[action-url]: https://github.com/JuliaArrays/OffsetArrays.jl/actions\n\n[codecov-img]: https://codecov.io/github/JuliaArrays/OffsetArrays.jl/coverage.svg?branch=master\n[codecov-url]: https://codecov.io/gh/JuliaArrays/OffsetArrays.jl\n\n[docs-stable-img]: https://img.shields.io/badge/docs-stable-blue.svg\n[docs-stable-url]: https://juliaarrays.github.io/OffsetArrays.jl/stable/\n[docs-dev-img]: https://img.shields.io/badge/docs-dev-blue.svg\n[docs-dev-url]: https://juliaarrays.github.io/OffsetArrays.jl/dev/\n\n[ver-img]: https://juliahub.com/docs/OffsetArrays/version.svg\n[ver-url]: https://juliahub.com/ui/Packages/OffsetArrays/UDEDl\n\n[deps-img]: https://juliahub.com/docs/OffsetArrays/deps.svg\n[deps-url]: https://juliahub.com/ui/Packages/OffsetArrays/UDEDl\n\n[doc_LinearIndices]: https://docs.julialang.org/en/v1/base/arrays/#Base.LinearIndices\n[doc_CartesianIndices]: https://docs.julialang.org/en/v1/base/arrays/#Base.IteratorsMD.CartesianIndices\n"
  },
  {
    "path": "benchmark/benchmarks.jl",
    "content": "using BenchmarkTools\nusing OffsetArrays\n\nconst dim = 1000\n\nx = Array{Float64}(undef, 2*dim);\ny = OffsetArray{Float64}(undef, -dim + 1 : dim);\nx2d = Array{Float64}(undef, 2*dim, 2*dim);\ny2d = OffsetArray{Float64}(undef, -dim + 1 : dim, -dim + 1 : dim);\n\ns = OffsetVector(1:dim, 0);\nsur = 1:dim;\nsior = OffsetArrays.IdOffsetRange(parent(s));\n\nfill1d(x) = for i in axes(x,1); x[i] = i; end\nfill2d(x) = for j in axes(x,2); for i in axes(x,1); x[i,j] = i + j; end; end\nupdate(x) = for i in axes(x,1); x[i] = x[i] + i; end\nupdate2d(x) = for j in axes(x,2); for i in axes(x,1); x[i,j] = x[i,j] + i + j; end; end\nupdate_eachindex(x) = for i in eachindex(x); x[i] = x[i] + i; end\n\nunsafe_fill(x) = @inbounds(for i in axes(x,1); x[i] = i; end)\nunsafe_fill2d(x) = @inbounds(for j in axes(x,2); for i in axes(x,1); x[i,j] = i + j; end; end)\nunsafe_update(x) = @inbounds(for i in axes(x,1); x[i] = x[i] + i; end)\nunsafe_update2d(x) = @inbounds(for j in axes(x,2); for i in axes(x,1); x[i,j] = x[i,j] + i + j; end; end)\nunsafe_update_eachindex(x) = @inbounds(for i in eachindex(x); x[i] = x[i] + i; end)\n\nvectorlinearindexing(a, ax) = a[ax]\nvectorCartesianindexing(a, ax1, ax2) = a[ax1, ax2]\nnestedvectorlinearindexing(a, ax1, ax2) = a[ax1[ax2]]\n\nmacro showbenchmark(ex)\n\tprint(ex, \" : \")\n\tquote\n\t\tprintln(@benchmark esc($ex))\n\tend\nend\n\n@showbenchmark fill1d(x)\n@showbenchmark fill1d(y)\n@showbenchmark fill2d(x2d)\n@showbenchmark fill2d(y2d)\n@showbenchmark update(x)\n@showbenchmark update(y)\n@showbenchmark update2d(x2d)\n@showbenchmark update2d(y2d)\n@showbenchmark update_eachindex(x)\n@showbenchmark update_eachindex(y)\n\n@showbenchmark unsafe_fill(x)\n@showbenchmark unsafe_fill(y)\n@showbenchmark unsafe_fill2d(x2d)\n@showbenchmark unsafe_fill2d(y2d)\n@showbenchmark unsafe_update(x)\n@showbenchmark unsafe_update(y)\n@showbenchmark unsafe_update2d(x2d)\n@showbenchmark unsafe_update2d(y2d)\n@showbenchmark unsafe_update_eachindex(x)\n@showbenchmark unsafe_update_eachindex(y)\n\n# Benchmarks of vector indexing using OffsetRanges as axes\n@showbenchmark vectorlinearindexing(x, s)\n@showbenchmark vectorlinearindexing(x, sur)\n@showbenchmark vectorlinearindexing(x, sior)\n@showbenchmark vectorlinearindexing(y, s)\n@showbenchmark vectorlinearindexing(y, sur)\n@showbenchmark vectorlinearindexing(y, sior)\n\n@showbenchmark vectorlinearindexing(sur, s)\n@showbenchmark vectorlinearindexing(sur, sur)\n@showbenchmark vectorlinearindexing(sur, sior)\n\n@showbenchmark vectorCartesianindexing(x2d, s, s)\n@showbenchmark vectorCartesianindexing(x2d, sur, sur)\n@showbenchmark vectorCartesianindexing(x2d, sior, sior)\n\n@showbenchmark nestedvectorlinearindexing(x, s, s)\n@showbenchmark nestedvectorlinearindexing(x, sur, sur)\n@showbenchmark nestedvectorlinearindexing(x, s, sior)\n@showbenchmark nestedvectorlinearindexing(x, sur, sior)\n@showbenchmark nestedvectorlinearindexing(x, sior, sior)\n@showbenchmark vectorlinearindexing(x, sior[sior])\n@showbenchmark nestedvectorlinearindexing(x, sur, sior)\n@showbenchmark vectorlinearindexing(x, sur[sior])\n@showbenchmark nestedvectorlinearindexing(x, sior, sur)\n@showbenchmark vectorlinearindexing(x, sior[sur])\n@showbenchmark nestedvectorlinearindexing(x, sur, sur)\n"
  },
  {
    "path": "docs/.gitignore",
    "content": "build/\nsite/\n"
  },
  {
    "path": "docs/Project.toml",
    "content": "[deps]\nDocumenter = \"e30172f5-a6a5-5a46-863b-614d45cd2de4\"\nJSON = \"682c06a0-de6a-54ab-a142-c8b1cf79cde6\"\nOffsetArrays = \"6fe1bfb0-de20-5000-8ca7-80f57d26f881\"\n\n[compat]\nDocumenter = \"0.27\"\nJSON = \"0.21\"\n"
  },
  {
    "path": "docs/make.jl",
    "content": "using Documenter, JSON\nusing OffsetArrays\n\nDocMeta.setdocmeta!(OffsetArrays, :DocTestSetup, :(using OffsetArrays); recursive=true)\n\nmakedocs(\n    sitename = \"OffsetArrays\",\n    format = Documenter.HTML(prettyurls = get(ENV, \"CI\", nothing) == \"true\"),\n    pages = [\"index.md\", \"internals.md\", \"reference.md\"],\n    modules = [OffsetArrays],\n    doctestfilters = [r\"at \\./.*\", r\"at /home.*\", r\"top-level scope.*\", r\"\\[\\d*\\]\\s*$\"],   # for backtraces\n)\n\n# a workdaround to github action that only push preview when PR has \"push_preview\" labels\n# issue: https://github.com/JuliaDocs/Documenter.jl/issues/1225\nfunction should_push_preview(event_path = get(ENV, \"GITHUB_EVENT_PATH\", nothing))\n    event_path === nothing && return false\n    event = JSON.parsefile(event_path)\n    haskey(event, \"pull_request\") || return false\n    labels = [x[\"name\"] for x in event[\"pull_request\"][\"labels\"]]\n    return \"push_preview\" in labels\n end\n\ndeploydocs(\n    repo = \"github.com:JuliaArrays/OffsetArrays.jl.git\",\n    push_preview = should_push_preview()\n)\n"
  },
  {
    "path": "docs/src/index.md",
    "content": "# OffsetArrays.jl\n\nOffsetArrays provides Julia users with arrays that have arbitrary\nindices, similar to those found in some other programming languages\nlike Fortran. Below is the basic usage found in the README, followed\nby a couple of short examples illustrating circumstances in which\nOffsetArrays can be useful. For a lengthier discussion, see\n[this blog post](https://julialang.org/blog/2017/04/offset-arrays/).\n\n## Usage\n\nYou can construct such arrays as follows:\n\n```julia\nOA = OffsetArray(A, axis1, axis2, ...)\n```\n\nwhere you want `OA` to have axes `(axis1, axis2, ...)` and be indexed by values that\nfall within these axis ranges.\n\n```@repl index\nusing OffsetArrays\n\nA = Float64.(reshape(1:15, 3, 5))\n\nOA = OffsetArray(A, -1:1, 0:4) # OA will have axes (-1:1, 0:4)\n\nOA = OffsetArray(A, CartesianIndex(-1, 0):CartesianIndex(1, 4))\n\nOA[-1,0], OA[1,4]\n```\n\nYou could also pass integers as offsets, where `0` means no offsets are applied:\n\n```@repl index\nOA = OffsetArray(A, -2, -1)\n```\n\nWhen you create a new `OffsetArray` on the top of another `OffsetArray`, the offsets are\naccumulated:\n\n```@repl index\nOOA = OffsetArray(OA, 2, 1)\n```\n\nFor the special cases that you want to compensate the offset back to the ordinary 1-based array, you\ncan use [`OffsetArrays.no_offset_view(A)`](@ref). Furthermore, you could use\n`Base.require_one_based_indexing` if you want to ensure the array does not have offsets.\n\n```@repl index\nOffsetArrays.no_offset_view(OA)\n\nBase.require_one_based_indexing(ans)\n\nBase.require_one_based_indexing(OA)\n```\n\n[`OffsetArrays.Origin`](@ref) can be convenient if you want to directly specify the origin of the output\nOffsetArray, it will automatically compute the corresponding offsets. For example:\n\n```@repl index\nOffsetArray(A, OffsetArrays.Origin(-1, -1))\nOffsetArray(OA, OffsetArrays.Origin(-1, -1))\n```\n\nAn equivalent — but possibly more convenient — way to specify the origin of an array is\n\n```@repl index\nOffsetArrays.Origin(-1, -1)(A)\n```\n\nSometimes, it will be convenient to shift the center coordinate of the given array to `(0, 0, ...)`,\n`OffsetArrays.centered` is a helper for this very purpose:\n\n```@repl index\nAo = OffsetArrays.centered(A)\nAo[0, 0] == 8.0\n```\n\nand `OffsetArrays.center` tells you the center coordinate of given array:\n\n```@repl index\nc = OffsetArrays.center(A)\nA[c...] == 8.0\n```\n\n## Example: Relativistic Notation\n\nSuppose we have a position vector `r = [:x, :y, :z]` which is naturally one-based, ie. `r[1] == :x`, `r[2] == :y`,  `r[3] == :z` and we also want to construct a relativistic position vector which includes time as the 0th component. This can be done with OffsetArrays like\n\n```jldoctest; setup = :(using OffsetArrays)\njulia> r = [:x, :y, :z];\n\njulia> x = OffsetVector([:t, r...], 0:3)\n4-element OffsetArray(::Vector{Symbol}, 0:3) with eltype Symbol with indices 0:3:\n :t\n :x\n :y\n :z\n\njulia> x[0]\n:t\n\njulia> x[1:3]\n3-element Vector{Symbol}:\n :x\n :y\n :z\n```\n\n## Example: Polynomials\n\nSuppose one wants to represent the Laurent polynomial\n\n```math\n6/x + 5 - 2*x + 3*x^2 + x^3\n```\n\nThe coefficients of this polynomial are a naturally `-1` based list, since the `n`th element of the list\n(counting from `-1`) `6, 5, -2, 3, 1` is the coefficient corresponding to the `n`th power of `x`. This Laurent polynomial can be evaluated at say `x = 2` as follows.\n\n```jldoctest; setup = :(using OffsetArrays)\njulia> coeffs = OffsetVector([6, 5, -2, 3, 1], -1:3)\n5-element OffsetArray(::Vector{Int64}, -1:3) with eltype Int64 with indices -1:3:\n  6\n  5\n -2\n  3\n  1\n\njulia> polynomial(x, coeffs) = sum(coeffs[n]*x^n for n in eachindex(coeffs))\npolynomial (generic function with 1 method)\n\njulia> polynomial(2.0, coeffs)\n24.0\n```\n\nNotice our use of the `eachindex` function which does not assume that the given array starts at `1`.\n"
  },
  {
    "path": "docs/src/internals.md",
    "content": "# For developers\n\nWriting code that supports OffsetArrays is generally fairly straightforward.\nThe majority of cases can be handled with these tips:\n\n- replace many uses of `size` with `axes`\n- replace `1:length(A)` with `eachindex(A)`, or if you need an integer index with `LinearIndices(A)`\n- replace explicit allocations like `Array{Int}(undef, size(B))` with `similar(Array{Int}, axes(B))`\n\nMore information can be found in [Julia's developer documentation](https://docs.julialang.org/en/v1/devdocs/offset-arrays/).\nThe most subtle issues tend to arise around the axes, and further detail specific to\nOffsetArrays.jl follows below.\n\n## Internals\n\nHow does OffsetArrays work? The fundamental principle is very simple:\nan `OffsetArray` is just a wrapper around a \"parent\" array, together\nwith an index offset:\n\n```jldoctest oa; setup=:(using OffsetArrays)\njulia> oa = OffsetArray([1 2; 3 4], 0:1, 5:6)\n2×2 OffsetArray(::Matrix{Int64}, 0:1, 5:6) with eltype Int64 with indices 0:1×5:6:\n 1  2\n 3  4\n\njulia> parent(oa)\n2×2 Matrix{Int64}:\n 1  2\n 3  4\n\njulia> oa.offsets\n(-1, 4)\n```\n\nSo `parent(oa)` is the original array we constructed it with, and `oa.offsets` is a tuple,\neach entry encoding the index-shift to be applied along the corresponding axis.\nWhen you index `oa[i,j]`, it \"translates\" the `i,j` indexes back to the parent array's\nindexes and then returns the value in the parent.\n\n## The axes of OffsetArrays\n\nThe internal of offset computing is achieved by [`IdOffsetRange`](@ref OffsetArrays.IdOffsetRange)\ntype:\n\n```jldoctest oa\njulia> ax = axes(oa, 2)\nOffsetArrays.IdOffsetRange(values=5:6, indices=5:6)\n```\n\nThis has a similar design to `Base.IdentityUnitRange` that `ax[x] == x` always holds.\n\n```jldoctest oa\njulia> ax[5]\n5\njulia> ax[1]\nERROR: BoundsError: attempt to access 2-element OffsetArrays.IdOffsetRange{Int64, Base.OneTo{Int64}} with indices 5:6 at index [1]\n[...]\n```\n\nThis property makes sure that they tend to be their own axes:\n\n```jldoctest oa\njulia> axes(ax)\n(OffsetArrays.IdOffsetRange(values=5:6, indices=5:6),)\n\njulia> axes(ax[ax])\n(OffsetArrays.IdOffsetRange(values=5:6, indices=5:6),)\n```\n\nThis example of indexing is [idempotent](https://en.wikipedia.org/wiki/Idempotence).\nThis is a useful characteristic for ensuring the \"fundamental axiom\" of generalized indexing,\nthat `a[ax][i] == a[ax[i]]`:\n\n```jldoctest; setup=:(using OffsetArrays)\njulia> oa2 = OffsetArray([5, 10, 15, 20], 0:3)\n4-element OffsetArray(::Vector{Int64}, 0:3) with eltype Int64 with indices 0:3:\n  5\n 10\n 15\n 20\n\njulia> ax2 = axes(oa2, 1)\nOffsetArrays.IdOffsetRange(values=0:3, indices=0:3)\n\njulia> oa2[2]\n15\n\njulia> oa2[ax2][2]\n15\n\njulia> oa2[ax2[2]]\n15\n```\n\n`IdOffsetRange`s apply the offset both to the values and the indices of the range, and otherwise preserve the parent range.\n\n!!! warning\n\n    There are circumstances where constructing a specific type of `IdOffsetRange` cannot be supported without changing the axes of the range (see [`OffsetArrays.IdOffsetRange`](@ref).)\n    In the future, this package will distinguish between *construction*  and *conversion*:\n\n    - construction (aka, *coercion*) will always succeed, even if it has to change the axes of the result (Examples: `RangeType(rng)`, `typeof(rng1)(rng2)`)\n    - conversion will succeed only if it can preserve both the values and the axes (Examples: `convert(RangeType, rng)`, `oftype(rng1, rng2)`)\n\n    While these behave equivalently now (conversion currently performs coercion), developers are encouraged to \"future-proof\" their code by choosing the behavior appropriate for each usage.\n\n\n## Wrapping other offset array types\n\nAn `OffsetArray` may wrap any subtype of `AbstractArray`, including ones that do not use `1`-based indexing. Such arrays however need to satisfy the fundamental axiom of idempotent indexing for things to work correctly. In other words, an axis of an offset array needs to have the same values as its own axis. This property is built into `OffsetArray`s if the parent uses 1-based indexing, but it's up to the user to ensure the correctness in case a type is to be wrapped that uses offset indices.\n\nWe demonstrate this through an example by creating a custom 0-based range type that we wrap in an `OffsetArray`:\n\n```jldoctest zerobasedrange; setup=:(using OffsetArrays)\njulia> struct ZeroBasedRange{T,A<:AbstractRange{T}} <: AbstractRange{T}\n           a :: A\n           function ZeroBasedRange(a::AbstractRange{T}) where {T}\n               @assert !Base.has_offset_axes(a)\n               new{T, typeof(a)}(a)\n           end\n       end;\n\njulia> Base.parent(A::ZeroBasedRange) = A.a;\n\njulia> Base.first(A::ZeroBasedRange) = first(A.a);\n\njulia> Base.length(A::ZeroBasedRange) = length(A.a);\n\njulia> Base.last(A::ZeroBasedRange) = last(A.a);\n\njulia> Base.size(A::ZeroBasedRange) = size(A.a);\n\njulia> Base.axes(A::ZeroBasedRange) = map(x -> 0:x-1, size(A.a));\n\njulia> Base.getindex(A::ZeroBasedRange, i::Int) = A.a[i + 1];\n\njulia> Base.step(A::ZeroBasedRange) = step(A.a);\n\njulia> function Base.show(io::IO, A::ZeroBasedRange)\n           show(io, A.a)\n           print(io, \" with indices $(axes(A,1))\")\n       end;\n```\n\nThis definition of a `ZeroBasedRange` appears to have the correct indices, for example:\n\n```jldoctest zerobasedrange\njulia> z = ZeroBasedRange(1:4)\n1:4 with indices 0:3\n\njulia> z[0]\n1\n\njulia> z[3]\n4\n```\n\nHowever this does not use idempotent indexing, as the axis of a `ZeroBasedRange` is not its own axis.\n\n```jldoctest zerobasedrange\njulia> axes(z, 1)\n0:3\n\njulia> axes(axes(z, 1), 1)\nBase.OneTo(4)\n```\n\nThis will lead to complications in certain functions --- for example `LinearIndices` --- that tends to implicitly assume idempotent indexing. In this case the `LinearIndices` of `z` will not match its axis.\n\n```jldoctest zerobasedrange\njulia> LinearIndices(z)\n4-element LinearIndices{1, Tuple{UnitRange{Int64}}}:\n 1\n 2\n 3\n 4\n```\n\nWrapping such a type in an `OffsetArray` might lead to unexpected bugs.\n\n```jldoctest zerobasedrange\njulia> zo = OffsetArray(z, 1);\n\njulia> axes(zo, 1)\nOffsetArrays.IdOffsetRange(values=1:4, indices=2:5)\n\njulia> Array(zo)\nERROR: BoundsError: attempt to access 4-element UnitRange{Int64} at index [5]\n[...]\n```\n\nThe `Array` conversion errors despite `zo` having 1-based indices. The function `axes(zo, 1)` hints at the underlying problem --- the values and the indices of the axis are different. We may check that the axis of `zo` is not its own axis:\n\n```jldoctest zerobasedrange\njulia> axes(zo, 1)\nOffsetArrays.IdOffsetRange(values=1:4, indices=2:5)\n\njulia> axes(axes(zo, 1), 1)\nOffsetArrays.IdOffsetRange(values=2:5, indices=2:5)\n```\n\nIn this case the bug may be fixed by defining the `axes` of a `ZeroBasedRange` to be idempotent, for example using the `OffsetArrays.IdentityUnitRange` wrapper:\n\n```jldoctest zerobasedrange\njulia> Base.axes(A::ZeroBasedRange) = map(x -> OffsetArrays.IdentityUnitRange(0:x-1), size(A.a))\n\njulia> axes(zo, 1)\nOffsetArrays.IdOffsetRange(values=1:4, indices=1:4)\n```\n\nWith this new definition, the values and indices of the axis are identical, which makes indexing idempotent. The conversion to an `Array` works as expected now:\n\n```jldoctest zerobasedrange\njulia> Array(zo)\n4-element Vector{Int64}:\n 1\n 2\n 3\n 4\n```\n\n## Caveats\n\nBecause `IdOffsetRange` behaves quite differently to the normal `UnitRange` type, there are some\ncases that you should be aware of, especially when you are working with multi-dimensional arrays.\n\nOne such cases is `getindex`:\n\n```jldoctest getindex; setup = :(using OffsetArrays)\njulia> Ao = zeros(-3:3, -3:3); Ao[:] .= 1:49;\n\njulia> Ao[-3:0, :] |> axes # the first dimension does not preserve offsets\n(OffsetArrays.IdOffsetRange(values=1:4, indices=1:4), OffsetArrays.IdOffsetRange(values=-3:3, indices=-3:3))\n\njulia> Ao[-3:0, -3:3] |> axes # neither dimensions preserve offsets\n(Base.OneTo(4), Base.OneTo(7))\n\njulia> Ao[axes(Ao)...] |> axes # offsets are preserved\n(OffsetArrays.IdOffsetRange(values=-3:3, indices=-3:3), OffsetArrays.IdOffsetRange(values=-3:3, indices=-3:3))\n\njulia> Ao[:] |> axes # This is linear indexing\n(Base.OneTo(49),)\n```\n\nNote that if you pass a `UnitRange`, the offsets in corresponding dimension will not be preserved.\nThis might look weird at first, but since it follows the `a[ax][i] == a[ax[i]]` rule, it is not a\nbug.\n\n```jldoctest getindex\njulia> I = -3:0; # UnitRange always starts at index 1\n\njulia> Ao[I, 0][1] == Ao[I[1], 0]\ntrue\n\njulia> ax = axes(Ao, 1) # ax starts at index -3\nOffsetArrays.IdOffsetRange(values=-3:3, indices=-3:3)\n\njulia> Ao[ax, 0][1] == Ao[ax[1], 0]\ntrue\n```\n\n## Using custom axis types\n\nWhile a wide variety of `AbstractUnitRange`s provided by `Base` may be used as indices to construct an `OffsetArray`, at times it might be convenient to define custom types. The `OffsetArray` constructor accepts any type that may be converted to an `AbstractUnitRange`. This proceeds through a two-step process. Let's assume that the constructor called is `OffsetArray(A, indstup)`, where `indstup` is a `Tuple` of indices.\n\n1. At the first step, the constructor calls `to_indices(A, axes(A), indstup)` to lower `indstup` to a `Tuple` of `AbstractUnitRange`s. This step converts --- among other things --- `Colon`s to axis ranges. Custom types may extend `Base.to_indices(A, axes(A), indstup)` with the desired conversion of `indstup` to `Tuple{Vararg{AbstractUnitRange{Int}}}` if this is feasible.\n\n2. At the second step, the result obtained from the previous step treated again to convert it to a `Tuple` of `AbstractUnitRange`s to handle cases where the first step doesn't achieve this. An additional customization option may be specified at this stage: a type may be converted either to a single `AbstractUnitRange{Int}`, or to a `Tuple` of them. A type might specify which of these two behaviours is desired by extending [`OffsetArrays.AxisConversionStyle`](@ref). An example of a type that is acted upon at this stage is `CartesianIndices`, which is converted to a `Tuple` of `AbstractUnitRange`s.\n\nFor example, here are a couple of custom type that facilitate zero-based indexing:\n\n```jldoctest; setup = :(using OffsetArrays)\njulia> struct ZeroBasedIndexing end\n\njulia> Base.to_indices(A, inds, ::Tuple{ZeroBasedIndexing}) = map(x -> 0:length(x)-1, inds)\n\njulia> a = zeros(3, 3);\n\njulia> oa = OffsetArray(a, ZeroBasedIndexing());\n\njulia> axes(oa)\n(OffsetArrays.IdOffsetRange(values=0:2, indices=0:2), OffsetArrays.IdOffsetRange(values=0:2, indices=0:2))\n```\n\nIn this example we had to define the action of `to_indices` as the type `ZeroBasedIndexing` did not have a familiar hierarchy. Things are even simpler if we subtype `AbstractUnitRange`, in which case we need to define `first` and `length` for the custom range to be able to use it as an axis:\n\n```jldoctest; setup = :(using OffsetArrays)\njulia> struct ZeroTo <: AbstractUnitRange{Int}\n       n :: Int\n       ZeroTo(n) = new(n < 0 ? -1 : n)\n       end\n\njulia> Base.first(::ZeroTo) = 0\n\njulia> Base.length(r::ZeroTo) = r.n + 1\n\njulia> oa = OffsetArray(zeros(2,2), ZeroTo(1), ZeroTo(1));\n\njulia> axes(oa)\n(OffsetArrays.IdOffsetRange(values=0:1, indices=0:1), OffsetArrays.IdOffsetRange(values=0:1, indices=0:1))\n```\n\nNote that zero-based indexing may also be achieved using the pre-defined type [`OffsetArrays.Origin`](@ref).\n"
  },
  {
    "path": "docs/src/reference.md",
    "content": "# Reference\n\n```@docs\nOffsetArray\nOffsetVector\nOffsetMatrix\nOffsetArrays.Origin\nOffsetArrays.IdOffsetRange\nOffsetArrays.no_offset_view\nOffsetArrays.AxisConversionStyle\nOffsetArrays.center\nOffsetArrays.centered\n```\n"
  },
  {
    "path": "ext/OffsetArraysAdaptExt.jl",
    "content": "module OffsetArraysAdaptExt\n\nusing OffsetArrays, Adapt\n\n##\n# Adapt allows for automatic conversion of CPU OffsetArrays to GPU OffsetArrays\n##\nimport Adapt\nAdapt.adapt_structure(to, O::OffsetArray) = OffsetArrays.parent_call(x -> Adapt.adapt(to, x), O)\n\n@static if isdefined(Adapt, :parent_type)\n    # To support Adapt 3.0 which doesn't have parent_type defined\n    Adapt.parent_type(::Type{OffsetArray{T,N,AA}}) where {T,N,AA} = AA\n    Adapt.unwrap_type(W::Type{<:OffsetArray}) = unwrap_type(parent_type(W))\nend\n\nend\n"
  },
  {
    "path": "src/OffsetArrays.jl",
    "content": "module OffsetArrays\n\nusing Base: tail, @propagate_inbounds\n@static if !isdefined(Base, :IdentityUnitRange)\n    const IdentityUnitRange = Base.Slice\nelse\n    using Base: IdentityUnitRange\nend\n\nexport OffsetArray, OffsetMatrix, OffsetVector\n\nconst IIUR = IdentityUnitRange{<:AbstractUnitRange{<:Integer}}\n\ninclude(\"axes.jl\")\ninclude(\"utils.jl\")\ninclude(\"origin.jl\")\n\n# Technically we know the length of CartesianIndices but we need to convert it first, so here we\n# don't put it in OffsetAxisKnownLength.\nconst OffsetAxisKnownLength = Union{Integer, AbstractUnitRange}\nconst OffsetAxis = Union{OffsetAxisKnownLength, Colon}\nconst ArrayInitializer = Union{UndefInitializer, Missing, Nothing}\n\n## OffsetArray\n\"\"\"\n    OffsetArray(A, indices...)\n\nReturn an `AbstractArray` that shares element type and size with the first argument but\nuses the supplied `indices` to infer its axes. If all the indices are `AbstractUnitRange`s then\nthese are directly used as the axis span along each dimension. Refer to the examples below for other\npermissible types.\n\nAlternatively it's possible to specify the coordinates of one corner of the array\nand have the axes be computed automatically from the size of `A`.\nThis constructor makes it convenient to shift to\nan arbitrary starting index along each axis, for example to a zero-based indexing scheme followed by\narrays in languages such as C and Python.\nSee [`Origin`](@ref) and the examples below for this usage.\n\n# Example: offsets\n\nThere are two types of `indices`: integers and ranges-like types.\n\nIntegers are recognized as offsets, where `0` means no offsets are applied:\n\n```jldoctest; setup=:(using OffsetArrays)\njulia> A = OffsetArray(reshape(1:6, 2, 3), -1, -2)\n2×3 OffsetArray(reshape(::UnitRange{$Int}, 2, 3), 0:1, -1:1) with eltype $Int with indices 0:1×-1:1:\n 1  3  5\n 2  4  6\n\njulia> A[0, 1]\n5\n```\n\nExamples of range-like types are: `UnitRange` (e.g, `-1:2`), `CartesianIndices`,\nand `Colon()` (or concisely `:`). A `UnitRange` specifies the axis span along one particular dimension,\n`CartesianIndices` specify the axis spans along multiple dimensions, and a `Colon` is a placeholder\nthat specifies that the `OffsetArray` shares its axis with its parent along that dimension.\n\n```jldoctest; setup=:(using OffsetArrays)\njulia> OffsetArray(reshape(1:6, 2, 3), 0:1, -1:1)\n2×3 OffsetArray(reshape(::UnitRange{$Int}, 2, 3), 0:1, -1:1) with eltype $Int with indices 0:1×-1:1:\n 1  3  5\n 2  4  6\n\njulia> OffsetArray(reshape(1:6, 2, 3), :, -1:1) # : as a placeholder to indicate that no offset is to be applied to the first dimension\n2×3 OffsetArray(reshape(::UnitRange{$Int}, 2, 3), 1:2, -1:1) with eltype $Int with indices 1:2×-1:1:\n 1  3  5\n 2  4  6\n```\n\nUse `CartesianIndices` to specify the coordinates of two diagonally opposite corners:\n\n```jldoctest; setup=:(using OffsetArrays)\njulia> OffsetArray(reshape(1:6, 2, 3), CartesianIndex(0, -1):CartesianIndex(1, 1))\n2×3 OffsetArray(reshape(::UnitRange{$Int}, 2, 3), 0:1, -1:1) with eltype $Int with indices 0:1×-1:1:\n 1  3  5\n 2  4  6\n```\n\nIntegers and range-like types may not be combined in the same call:\n\n```julia\njulia> OffsetArray(reshape(1:6, 2, 3), 0, -1:1)\nERROR: [...]\n```\n\n# Example: origin\n\n[`OffsetArrays.Origin`](@ref) may be used to specify the origin of the OffsetArray. The term origin here\nrefers to the corner with the lowest values of coordinates, such as the left edge for an `AbstractVector`,\nthe bottom left corner for an `AbstractMatrix` and so on. The coordinates of the origin sets the starting\nindex of the array along each dimension.\n\n```jldoctest; setup=:(using OffsetArrays)\njulia> a = [1 2; 3 4];\n\njulia> OffsetArray(a, OffsetArrays.Origin(0, 1))\n2×2 OffsetArray(::$(Array{Int,2}), 0:1, 1:2) with eltype $Int with indices 0:1×1:2:\n 1  2\n 3  4\n\njulia> OffsetArray(a, OffsetArrays.Origin(0)) # set the origin to zero along each dimension\n2×2 OffsetArray(::$(Array{Int, 2}), 0:1, 0:1) with eltype $Int with indices 0:1×0:1:\n 1  2\n 3  4\n```\n\n\n\"\"\"\nstruct OffsetArray{T,N,AA<:AbstractArray{T,N}} <: AbstractArray{T,N}\n    parent::AA\n    offsets::NTuple{N,Int}\n    @inline function OffsetArray{T, N, AA}(parent::AA, offsets::NTuple{N, Int}; checkoverflow = true) where {T, N, AA<:AbstractArray{T,N}}\n        # allocation of `map` on tuple is optimized away\n        checkoverflow && map(overflow_check, axes(parent), offsets)\n        new{T, N, AA}(parent, offsets)\n    end\nend\n\n\"\"\"\n    OffsetVector(v, index)\n\nType alias and convenience constructor for one-dimensional [`OffsetArray`](@ref)s.\n\"\"\"\nconst OffsetVector{T,AA<:AbstractVector{T}} = OffsetArray{T,1,AA}\n\n\"\"\"\n    OffsetMatrix(A, index1, index2)\n\nType alias and convenience constructor for two-dimensional [`OffsetArray`](@ref)s.\n\"\"\"\nconst OffsetMatrix{T,AA<:AbstractMatrix{T}} = OffsetArray{T,2,AA}\n\n# checks if the offset may be added to the range without overflowing\nfunction overflow_check(r::AbstractUnitRange, offset::Integer)\n    Base.hastypemax(eltype(r)) || return nothing\n    # This gives some performance boost https://github.com/JuliaLang/julia/issues/33273\n    throw_upper_overflow_error(val) = throw(OverflowError(\"offset should be <= $(typemax(Int) - val) corresponding to the axis $r, received an offset $offset\"))\n    throw_lower_overflow_error(val) = throw(OverflowError(\"offset should be >= $(typemin(Int) - val) corresponding to the axis $r, received an offset $offset\"))\n\n    # With ranges in the picture, first(r) might not necessarily be < last(r)\n    # we therefore use the min and max of first(r) and last(r) to check for overflow\n    firstlast_min, firstlast_max = minmax(first(r), last(r))\n\n    if offset > 0 && firstlast_max > typemax(Int) - offset\n        throw_upper_overflow_error(firstlast_max)\n    elseif offset < 0 && firstlast_min < typemin(Int) - offset\n        throw_lower_overflow_error(firstlast_min)\n    end\n    return nothing\nend\n\n# Tuples of integers are treated as offsets\n# Empty Tuples are handled here\n@inline function OffsetArray(A::AbstractArray, offsets::Tuple{Vararg{Integer}}; kw...)\n    _checkindices(A, offsets, \"offsets\")\n    OffsetArray{eltype(A), ndims(A), typeof(A)}(A, offsets; kw...)\nend\n\n# These methods are necessary to disallow incompatible dimensions for\n# the OffsetVector and the OffsetMatrix constructors\nfor (FT, ND) in ((:OffsetVector, :1), (:OffsetMatrix, :2))\n    @eval @inline function $FT(A::AbstractArray{<:Any,$ND}, offsets::Tuple{Vararg{Integer}}; kw...)\n        _checkindices(A, offsets, \"offsets\")\n        OffsetArray{eltype(A), $ND, typeof(A)}(A, offsets; kw...)\n    end\n    FTstr = string(FT)\n    @eval @inline function $FT(A::AbstractArray, offsets::Tuple{Vararg{Integer}}; kw...)\n        throw(ArgumentError($FTstr*\" requires a \"*string($ND)*\"D array\"))\n    end\nend\n\n## OffsetArray constructors\nfor FT in (:OffsetArray, :OffsetVector, :OffsetMatrix)\n    # Nested OffsetArrays may strip off the wrapper and collate the offsets\n    # empty tuples are handled here\n    @eval @inline function $FT(A::OffsetArray, offsets::Tuple{Vararg{Int}}; checkoverflow = true)\n        _checkindices(A, offsets, \"offsets\")\n        # ensure that the offsets may be added together without an overflow\n        checkoverflow && map(overflow_check, axes(A), offsets)\n        I = map(+, _offsets(A, parent(A)), offsets)\n        $FT(parent(A), I, checkoverflow = false)\n    end\n    @eval @inline function $FT(A::OffsetArray, offsets::Tuple{Integer,Vararg{Integer}}; kw...)\n        $FT(A, map(Int, offsets); kw...)\n    end\n\n    # In general, indices get converted to AbstractUnitRanges.\n    # CartesianIndices{N} get converted to N ranges\n    @eval @inline function $FT(A::AbstractArray, inds::Tuple{Any,Vararg{Any}}; kw...)\n        $FT(A, _toAbstractUnitRanges(to_indices(A, axes(A), inds)); kw...)\n    end\n\n    # convert ranges to offsets\n    @eval @inline function $FT(A::AbstractArray, inds::Tuple{AbstractUnitRange,Vararg{AbstractUnitRange}}; kw...)\n        _checkindices(A, inds, \"indices\")\n        # Performance gain by wrapping the error in a function: see https://github.com/JuliaLang/julia/issues/37558\n        throw_dimerr(lA, lI) = throw(DimensionMismatch(\"supplied axes do not agree with the size of the array (got size $lA for the array and $lI for the indices\"))\n        lA = size(A)\n        lI = map(length, inds)\n        lA == lI || throw_dimerr(lA, lI)\n        $FT(A, map(_offset, axes(A), inds); kw...)\n    end\n\n    @eval @inline $FT(A::AbstractArray, inds...; kw...) = $FT(A, inds; kw...)\n    @eval @inline $FT(A::AbstractArray; checkoverflow = false) = $FT(A, ntuple(zero, Val(ndims(A))), checkoverflow = checkoverflow)\n\n    @eval @inline $FT(A::AbstractArray, origin::Origin; checkoverflow = true) = $FT(A, origin.index .- first.(axes(A)); checkoverflow = checkoverflow)\nend\n\n(o::Origin)(A::AbstractArray) = OffsetArray(no_offset_view(A), o)\nOrigin(A::AbstractArray) = Origin(first.(axes(A)))\n\n# conversion-related methods\n@inline OffsetArray{T}(M::AbstractArray, I...; kw...) where {T} = OffsetArray{T,ndims(M)}(M, I...; kw...)\n\n@inline function OffsetArray{T,N}(M::AbstractArray{<:Any,N}, I...; kw...) where {T,N}\n    M2 = _of_eltype(T, M)\n    OffsetArray{T,N}(M2, I...; kw...)\nend\n@inline OffsetArray{T,N}(M::OffsetArray{T,N}, I...; kw...) where {T,N} = OffsetArray(M, I...; kw...)\n@inline OffsetArray{T,N}(M::AbstractArray{T,N}, I...; kw...) where {T,N} = OffsetArray{T,N,typeof(M)}(M, I...; kw...)\n\n@inline OffsetArray{T,N,A}(M::AbstractArray{<:Any,N}, I...; kw...) where {T,N,A<:AbstractArray{T,N}} = OffsetArray{T,N,A}(M, I; kw...)\n@inline function OffsetArray{T,N,A}(M::AbstractArray{<:Any,N}, I::NTuple{N,Int}; checkoverflow = true) where {T,N,A<:AbstractArray{T,N}}\n    checkoverflow && map(overflow_check, axes(M), I)\n    Mv = no_offset_view(M)\n    MvA = convert(A, Mv)::A\n    Iof = map(+, _offsets(M), I)\n    OffsetArray{T,N,A}(MvA, Iof, checkoverflow = false)\nend\n@inline function OffsetArray{T, N, AA}(parent::AbstractArray{<:Any,N}, offsets::NTuple{N, Integer}; kw...) where {T, N, AA<:AbstractArray{T,N}}\n    OffsetArray{T, N, AA}(parent, map(Int, offsets)::NTuple{N,Int}; kw...)\nend\n@inline function OffsetArray{T,N,A}(M::AbstractArray{<:Any,N}, I::Tuple{AbstractUnitRange,Vararg{AbstractUnitRange}}; kw...) where {T,N,A<:AbstractArray{T,N}}\n    _checkindices(M, I, \"indices\")\n    # Performance gain by wrapping the error in a function: see https://github.com/JuliaLang/julia/issues/37558\n    throw_dimerr(lA, lI) = throw(DimensionMismatch(\"supplied axes do not agree with the size of the array (got size $lA for the array and $lI for the indices\"))\n    lM = size(M)\n    lI = map(length, I)\n    lM == lI || throw_dimerr(lM, lI)\n    OffsetArray{T,N,A}(M, map(_offset, axes(M), I); kw...)\nend\n@inline function OffsetArray{T,N,A}(M::AbstractArray{<:Any,N}, I::Tuple; kw...) where {T,N,A<:AbstractArray{T,N}}\n    OffsetArray{T,N,A}(M, _toAbstractUnitRanges(to_indices(M, axes(M), I)); kw...)\nend\n@inline function OffsetArray{T,N,A}(M::AbstractArray{<:Any,N}; kw...) where {T,N,A<:AbstractArray{T,N}}\n    Mv = no_offset_view(M)\n    MvA = convert(A, Mv)::A\n    OffsetArray{T,N,A}(MvA, _offsets(M); kw...)\nend\n@inline OffsetArray{T,N,A}(M::A; checkoverflow = false) where {T,N,A<:AbstractArray{T,N}} = OffsetArray{T,N,A}(M, ntuple(zero, Val(N)); checkoverflow = checkoverflow)\n\nBase.convert(::Type{T}, M::AbstractArray) where {T<:OffsetArray} = M isa T ? M : T(M)\n\n@inline AbstractArray{T,N}(M::OffsetArray{S,N}) where {T,S,N} = OffsetArray{T}(M)\n\n# array initialization\n@inline function OffsetArray{T,N}(init::ArrayInitializer, inds::Tuple{Vararg{OffsetAxisKnownLength}}; kw...) where {T,N}\n    _checkindices(N, inds, \"indices\")\n    AA = Array{T,N}(init, map(_indexlength, inds))\n    OffsetArray{T, N, typeof(AA)}(AA, map(_indexoffset, inds); kw...)\nend\n@inline function OffsetArray{T, N}(init::ArrayInitializer, inds::Tuple; kw...) where {T, N}\n    OffsetArray{T, N}(init, _toAbstractUnitRanges(inds); kw...)\nend\n@inline OffsetArray{T,N}(init::ArrayInitializer, inds...; kw...) where {T,N} = OffsetArray{T,N}(init, inds; kw...)\n\n@inline OffsetArray{T}(init::ArrayInitializer, inds::NTuple{N, OffsetAxisKnownLength}; kw...) where {T,N} = OffsetArray{T,N}(init, inds; kw...)\n@inline function OffsetArray{T}(init::ArrayInitializer, inds::Tuple; kw...) where {T}\n    OffsetArray{T}(init, _toAbstractUnitRanges(inds); kw...)\nend\n@inline OffsetArray{T}(init::ArrayInitializer, inds...; kw...) where {T} = OffsetArray{T}(init, inds; kw...)\n\nBase.IndexStyle(::Type{OA}) where {OA<:OffsetArray} = IndexStyle(parenttype(OA))\nparenttype(::Type{OffsetArray{T,N,AA}}) where {T,N,AA} = AA\nparenttype(A::OffsetArray) = parenttype(typeof(A))\n\nBase.parent(A::OffsetArray) = A.parent\n\n# TODO: Ideally we would delegate to the parent's broadcasting implementation, but that\n#       is currently broken in sufficiently many implementation, namely RecursiveArrayTools, DistributedArrays\n#       and StaticArrays, that it will take concentrated effort to get this working across the ecosystem.\n#       The goal would be to have `OffsetArray(CuArray) .+ 1 == OffsetArray{CuArray}`.\n# Base.Broadcast.BroadcastStyle(::Type{<:OffsetArray{<:Any, <:Any, AA}}) where AA = Base.Broadcast.BroadcastStyle(AA)\n\n@inline Base.size(A::OffsetArray) = size(parent(A))\n# specializing length isn't necessary, as length(A) = prod(size(A)),\n# but specializing length enables constant-propagation for statically sized arrays\n# see https://github.com/JuliaArrays/OffsetArrays.jl/pull/304\n@inline Base.length(A::OffsetArray) = length(parent(A))\n\n@inline Base.axes(A::OffsetArray) = map(IdOffsetRange, axes(parent(A)), A.offsets)\n@inline Base.axes(A::OffsetArray, d) = d <= ndims(A) ? IdOffsetRange(axes(parent(A), d), A.offsets[d]) : IdOffsetRange(axes(parent(A), d))\n@inline Base.axes1(A::OffsetArray{T,0}) where {T} = IdOffsetRange(axes(parent(A), 1))  # we only need to specialize this one\n\n# Issue 128\n# See https://github.com/JuliaLang/julia/issues/37274 for the issue reported in Base\n# The fix https://github.com/JuliaLang/julia/pull/39404 should be available on v1.6\n# The following method is added on older Julia versions to ensure correct behavior for OffsetVectors\nif VERSION < v\"1.6\"\n    @inline function Base.compute_linindex(A::OffsetVector, I::NTuple{N,Any}) where N\n        IP = Base.fill_to_length(axes(A), Base.OneTo(1), Val(N))\n        Base.compute_linindex(first(LinearIndices(A)), 1, IP, I)\n    end\nend\n\n# Utils to translate a function to the parent while preserving offsets\nunwrap(x) = x, identity\nunwrap(x::OffsetArray) = parent(x), data -> OffsetArray(data, x.offsets, checkoverflow = false)\nfunction parent_call(f, x)\n    parent, wrap_offset = unwrap(x)\n    wrap_offset(f(parent))\nend\n\nBase.similar(A::OffsetArray, ::Type{T}, dims::Dims) where T =\n    similar(parent(A), T, dims)\nfunction Base.similar(A::AbstractArray, ::Type{T}, shape::Tuple{OffsetAxisKnownLength,Vararg{OffsetAxisKnownLength}}) where T\n    # strip IdOffsetRanges to extract the parent range and use it to generate the array\n    new_shape = map(_strip_IdOffsetRange, shape)\n    # route through _similar_axes_or_length to avoid a stack overflow if map(_strip_IdOffsetRange, shape) === shape\n    # This tries to use new_shape directly in similar if similar(A, T, ::typeof(new_shape)) is defined\n    # If this fails, it calls similar(A, T, map(_indexlength, new_shape)) to use the size along each axis\n    # to generate the new array\n    P = _similar_axes_or_length(A, T, new_shape, shape)\n    return OffsetArray(P, map(_offset, axes(P), shape))\nend\nBase.similar(::Type{A}, sz::Tuple{Vararg{Int}}) where {A<:OffsetArray} = similar(Array{eltype(A)}, sz)\nfunction Base.similar(::Type{T}, shape::Tuple{OffsetAxisKnownLength,Vararg{OffsetAxisKnownLength}}) where {T<:AbstractArray}\n    new_shape = map(_strip_IdOffsetRange, shape)\n    P = _similar_axes_or_length(T, new_shape, shape)\n    OffsetArray(P, map(_offset, axes(P), shape))\nend\n# Try to use the axes to generate the parent array type\n# This is useful if the axes have special meanings, such as with static arrays\n# This method is hit if at least one axis provided to similar(A, T, axes) is an IdOffsetRange\n# For example this is hit when similar(A::OffsetArray) is called,\n# which expands to similar(A, eltype(A), axes(A))\n_similar_axes_or_length(A, T, ax, ::Any) = similar(A, T, ax)\n_similar_axes_or_length(AT, ax, ::Any) = similar(AT, ax)\n# Handle the general case by resorting to lengths along each axis\n# This is hit if none of the axes provided to similar(A, T, axes) are IdOffsetRanges,\n# and if similar(A, T, axes::AX) is not defined for the type AX.\n# In this case the best that we can do is to create a mutable array of the correct size\n_similar_axes_or_length(A, T, ax::I, ::I) where {I} = similar(A, T, map(_indexlength, ax))\n_similar_axes_or_length(AT, ax::I, ::I) where {I} = similar(AT, map(_indexlength, ax))\n\n# reshape accepts a single colon\n# this method is limited to AbstractUnitRange{<:Integer} to avoid method overwritten errors if Base defines the same,\n# see https://github.com/JuliaLang/julia/pull/56850\nBase.reshape(A::AbstractArray, inds::Union{Integer, Colon, AbstractUnitRange{<:Integer}}...) = reshape(A, inds)\nfunction Base.reshape(A::AbstractArray, inds::Tuple{Vararg{OffsetAxis}})\n    AR = reshape(no_offset_view(A), map(_indexlength, inds))\n    O = OffsetArray(AR, map(_offset, axes(AR), inds))\n    return _popreshape(O, axes(AR), _filterreshapeinds(inds))\nend\n\n# Reshaping OffsetArrays can \"pop\" the original OffsetArray wrapper and return\n# an OffsetArray(reshape(...)) instead of an OffsetArray(reshape(OffsetArray(...)))\n# Short-circuit for AbstractVectors if the axes are compatible to get around the Base restriction\n# to 1-based vectors\nfunction _reshape(A::AbstractVector, inds::Tuple{OffsetAxis})\n    @noinline throw_dimerr(ind::Integer) = throw(\n        DimensionMismatch(\"parent has $(size(A,1)) elements, which is incompatible with length $ind\"))\n    @noinline throw_dimerr(ind) = throw(\n        DimensionMismatch(\"parent has $(size(A,1)) elements, which is incompatible with indices $ind\"))\n    _checksize(first(inds), size(A,1)) || throw_dimerr(first(inds))\n    A\nend\n_reshape(A, inds) = _reshape2(A, inds)\n_reshape2(A, inds) = reshape(A, inds)\n# avoid a stackoverflow by relegating to the parent if no_offset_view returns an offsetarray\n_reshape2(A::OffsetArray, inds) = reshape(parent(A), inds)\n_reshape_nov(A, inds) = _reshape(no_offset_view(A), inds)\n\n# And for non-offset axes, we can just return a reshape of the parent directly\nBase.reshape(A::OffsetArray, inds::Tuple{Integer,Vararg{Integer}}) = _reshape_nov(A, inds)\nBase.reshape(A::OffsetArray, inds::Dims) = _reshape_nov(A, inds)\nif VERSION < v\"1.10.7\"\n    # the specialized reshape(parent::AbstractVector, ::Tuple{Colon}) is available in Base at least on this version\n    Base.reshape(A::OffsetVector, ::Tuple{Colon}) = A\n    Base.reshape(A::OffsetArray, inds::Tuple{Vararg{Union{Int,Colon}}}) = _reshape_nov(A, inds)\nend\n\n# permutedims in Base does not preserve axes, and can not be fixed in a non-breaking way\n# This is a stopgap solution\nBase.permutedims(v::OffsetVector) = reshape(v, (1, axes(v, 1)))\n\nif VERSION < v\"1.12.0-DEV.343\" # available in Base beyond this version\n    Base.fill(v, inds::NTuple{N, Union{Integer, AbstractUnitRange}}) where {N} =\n        fill!(similar(Array{typeof(v)}, inds), v)\n    Base.zeros(::Type{T}, inds::NTuple{N, Union{Integer, AbstractUnitRange}}) where {T, N} =\n        fill!(similar(Array{T}, inds), zero(T))\n    Base.ones(::Type{T}, inds::NTuple{N, Union{Integer, AbstractUnitRange}}) where {T, N} =\n        fill!(similar(Array{T}, inds), one(T))\n    Base.trues(inds::NTuple{N, Union{Integer, AbstractUnitRange}}) where {N} =\n        fill!(similar(BitArray, inds), true)\n    Base.falses(inds::NTuple{N, Union{Integer, AbstractUnitRange}}) where {N} =\n        fill!(similar(BitArray, inds), false)\nend\n\nBase.zero(A::OffsetArray) = parent_call(zero, A)\nBase.fill!(A::OffsetArray, x) = parent_call(Ap -> fill!(Ap, x), A)\n\n## Indexing\n\n# Note this gets the index of the parent *array*, not the index of the parent *range*\n# Here's how one can think about this:\n#   Δi = i - first(r)\n#   i′ = first(r.parent) + Δi\n# and one obtains the result below.\nparentindex(r::IdOffsetRange, i) = i - r.offset\n\n@propagate_inbounds Base.getindex(A::OffsetArray{<:Any,0})  = A.parent[]\n\n@inline function Base.getindex(A::OffsetArray{<:Any,N}, I::Vararg{Int,N}) where N\n    @boundscheck checkbounds(A, I...)\n    J = map(parentindex, axes(A), I)\n    @inbounds parent(A)[J...]\nend\n\n@propagate_inbounds Base.getindex(A::OffsetArray{<:Any,N}, c::Vararg{Colon,N}) where N =\n    parent_call(x -> getindex(x, c...), A)\n\n# With one Colon we use linear indexing.\n# In this case we may forward the index to the parent, as the information about the axes is lost\n# The exception to this is with OffsetVectors where the axis information is preserved,\n# but that case is handled by getindex(::OffsetArray{<:Any,N}, ::Vararg{Colon,N})\n@propagate_inbounds Base.getindex(A::OffsetArray, c::Colon) = A.parent[:]\n\n@inline function Base.getindex(A::OffsetVector, i::Int)\n    @boundscheck checkbounds(A, i)\n    @inbounds parent(A)[parentindex(Base.axes1(A), i)]\nend\n@propagate_inbounds Base.getindex(A::OffsetArray, i::Int)  = parent(A)[i]\n\n@inline function Base.setindex!(A::OffsetArray{T,N}, val, I::Vararg{Int,N}) where {T,N}\n    @boundscheck checkbounds(A, I...)\n    J = map(parentindex, axes(A), I)\n    @inbounds parent(A)[J...] = val\n    A\nend\n\n@inline function Base.setindex!(A::OffsetVector, val, i::Int)\n    @boundscheck checkbounds(A, i)\n    @inbounds parent(A)[parentindex(Base.axes1(A), i)] = val\n    A\nend\n@propagate_inbounds function Base.setindex!(A::OffsetArray, val, i::Int)\n    parent(A)[i] = val\n    A\nend\n\n@inline Base.iterate(a::OffsetArray, i...) = iterate(parent(a), i...)\n\nBase.in(x, A::OffsetArray) = in(x, parent(A))\nBase.copy(A::OffsetArray) = parent_call(copy, A)\n\nBase.strides(A::OffsetArray) = strides(parent(A))\nBase.elsize(::Type{OffsetArray{T,N,A}}) where {T,N,A} = Base.elsize(A)\nBase.cconvert(P::Type{Ptr{T}}, A::OffsetArray{T}) where {T} = Base.cconvert(P, parent(A))\nif VERSION < v\"1.11-\"\n    @inline Base.unsafe_convert(::Type{Ptr{T}}, A::OffsetArray{T}) where {T} = Base.unsafe_convert(Ptr{T}, parent(A))\nend\n\n# For fast broadcasting: ref https://discourse.julialang.org/t/why-is-there-a-performance-hit-on-broadcasting-with-offsetarrays/32194\nBase.dataids(A::OffsetArray) = Base.dataids(parent(A))\nBroadcast.broadcast_unalias(dest::OffsetArray, src::OffsetArray) = parent(dest) === parent(src) ? src : Broadcast.unalias(dest, src)\n\n### Special handling for AbstractRange\nconst OffsetRange{T} = OffsetVector{T,<:AbstractRange{T}}\nconst OffsetUnitRange{T} = OffsetVector{T,<:AbstractUnitRange{T}}\n\nBase.step(a::OffsetRange) = step(parent(a))\n\nBase.checkindex(::Type{Bool}, inds::AbstractUnitRange, or::OffsetRange) = Base.checkindex(Bool, inds, parent(or))\n\n# Certain special methods for linear indexing with integer ranges (or OffsetRanges)\n# These may bypass the default getindex(A, I...) pathway if the parent types permit this\n# For example AbstractUnitRanges and Arrays have special linear indexing behavior defined\n\n# If both the arguments are offset, we may unwrap the indices to call (::OffsetArray)[::AbstractRange{Int}]\n@propagate_inbounds function Base.getindex(A::OffsetArray, r::OffsetRange{Int})\n    _indexedby(A[parent(r)], axes(r))\nend\n# If the indices are offset, we may unwrap them and pass the parent to getindex\n@propagate_inbounds function Base.getindex(A::AbstractRange, r::OffsetRange{Int})\n    _indexedby(A[parent(r)], axes(r))\nend\n\n# An OffsetUnitRange might use the rapid getindex(::Array, ::AbstractUnitRange{Int}) for contiguous indexing\n@propagate_inbounds function Base.getindex(A::Array, r::OffsetUnitRange{Int})\n    B = A[_contiguousindexingtype(parent(r))]\n    OffsetArray(B, axes(r), checkoverflow = false)\nend\n\n# avoid hitting the slow method getindex(::Array, ::AbstractRange{Int})\n# instead use the faster getindex(::Array, ::UnitRange{Int})\nif VERSION <= v\"1.7.0-DEV.1039\"\n    @propagate_inbounds function Base.getindex(A::Array, r::Union{IdOffsetRange, IIUR})\n        B = A[_contiguousindexingtype(r)]\n        _indexedby(B, axes(r))\n    end\nend\n\n# Linear Indexing of OffsetArrays with AbstractUnitRanges may use the faster contiguous indexing methods\n@inline function Base.getindex(A::OffsetArray, r::AbstractUnitRange{Int})\n    @boundscheck checkbounds(A, r)\n    # nD OffsetArrays do not have their linear indices shifted, so we may forward the indices provided to the parent\n    @inbounds B = parent(A)[_contiguousindexingtype(r)]\n    _indexedby(B, axes(r))\nend\n@inline function Base.getindex(A::OffsetVector, r::AbstractUnitRange{Int})\n    @boundscheck checkbounds(A, r)\n    # OffsetVectors may have their linear indices shifted, so we subtract the offset from the indices provided\n    @inbounds B = parent(A)[_subtractoffset(r, A.offsets[1])]\n    _indexedby(B, axes(r))\nend\n\n# This method added mainly to index an OffsetRange with another range\n@inline function Base.getindex(A::OffsetVector, r::AbstractRange{Int})\n    @boundscheck checkbounds(A, r)\n    @inbounds B = parent(A)[_subtractoffset(r, A.offsets[1])]\n    _indexedby(B, axes(r))\nend\n\n# In general we would pass through getindex(A, I...) which calls to_indices(A, I) and finally to_index(I)\n# An OffsetUnitRange{Int} has an equivalent IdOffsetRange with the same values and axes,\n# something similar also holds for OffsetUnitRange{BigInt}\n# We may replace the former with the latter in an indexing operation to obtain a performance boost\n@inline function Base.to_index(r::OffsetUnitRange{<:Union{Int,BigInt}})\n    of = first(axes(r,1)) - 1\n    IdOffsetRange(_subtractoffset(parent(r), of), of)\nend\n\n@inline function _boundscheck_index_retaining_axes(r, s)\n    @boundscheck checkbounds(r, s)\n    @inbounds pr = r[UnitRange(s)]\n    _indexedby(pr, axes(s))\nend\n@inline _boundscheck_return(r, s) = (@boundscheck checkbounds(r, s); s)\n\nfor OR in [:IIUR, :IdOffsetRange]\n    for R in [:StepRange, :StepRangeLen, :LinRange, :UnitRange]\n        @eval @inline Base.getindex(r::$R, s::$OR) = _boundscheck_index_retaining_axes(r, s)\n    end\n\n    # this method is needed for ambiguity resolution\n    @eval @inline function Base.getindex(r::StepRangeLen{T,<:Base.TwicePrecision,<:Base.TwicePrecision}, s::$OR) where T\n        _boundscheck_index_retaining_axes(r, s)\n    end\nend\nBase.getindex(r::Base.OneTo, s::IdOffsetRange) = _boundscheck_index_retaining_axes(r, s)\nif VERSION < v\"1.7.0-beta2\"\n    Base.getindex(r::Base.OneTo, s::IIUR) = _boundscheck_index_retaining_axes(r, s)\nend\n\n# These methods are added to avoid ambiguities with Base.\n# The ones involving Base types should be ported to Base and version-limited here\n@inline Base.getindex(r::IdentityUnitRange, s::IIUR) = _boundscheck_return(r, s)\n@inline Base.getindex(r::IdentityUnitRange, s::IdOffsetRange) = _boundscheck_return(r, s)\nif IdentityUnitRange !== Base.Slice\n    @inline Base.getindex(r::Base.Slice, s::IIUR) = _boundscheck_return(r, s)\n    @inline Base.getindex(r::Base.Slice, s::IdOffsetRange) = _boundscheck_return(r, s)\nend\n\n# eltype conversion\n# This may use specialized map methods for the parent\nBase.map(::Type{T}, O::OffsetArray) where {T} = parent_call(x -> map(T, x), O)\nBase.map(::Type{T}, r::IdOffsetRange) where {T<:Real} = _indexedby(map(T, UnitRange(r)), axes(r))\nif eltype(IIUR) === Int\n    # This is type-piracy, but there is no way to convert an IdentityUnitRange to a non-Int type in Base\n    Base.map(::Type{T}, r::IdentityUnitRange) where {T<:Real} = _indexedby(map(T, UnitRange(r)), axes(r))\nend\n\nif VERSION < v\"1.7.2\"\n    # mapreduce is faster with an IdOffsetRange than with an OffsetUnitRange on Julia 1.6\n    # We therefore convert OffsetUnitRanges to IdOffsetRanges with the same values and axes\n    function Base.mapreduce(f, op, A1::OffsetUnitRange{<:Integer}, As::OffsetUnitRange{<:Integer}...; kw...)\n        As = (A1, As...)\n        ofs = map(A -> first(axes(A,1)) - 1, As)\n        AIds = map((A, of) -> IdOffsetRange(_subtractoffset(parent(A), of), of), As, ofs)\n        mapreduce(f, op, AIds...; kw...)\n    end\nend\n\n# Optimize certain reductions that treat an OffsetVector as a list\nfor f in [:minimum, :maximum, :extrema, :sum]\n    @eval Base.$f(r::OffsetRange) = $f(parent(r))\nend\n\nfunction Base.show(io::IO, r::OffsetRange)\n    show(io, r.parent)\n    print(io, \" with indices \", UnitRange(axes(r, 1)))\nend\nBase.show(io::IO, ::MIME\"text/plain\", r::OffsetRange) = show(io, r)\n\n\n### Some mutating functions defined only for OffsetVector ###\n\nBase.resize!(A::OffsetVector, nl::Integer) = (resize!(A.parent, nl); A)\nBase.push!(A::OffsetVector, x...) = (push!(A.parent, x...); A)\nBase.pop!(A::OffsetVector) = pop!(A.parent)\nBase.append!(A::OffsetVector, items) = (append!(A.parent, items); A)\nBase.empty!(A::OffsetVector) = (empty!(A.parent); A)\n\n# These functions keep the summary compact\nconst OffsetIndices = Union{IdOffsetRange, IdentityUnitRange{<:IdOffsetRange}}\nfunction Base.inds2string(inds::Tuple{OffsetIndices, Vararg{OffsetIndices}})\n    Base.inds2string(map(UnitRange, inds))\nend\nBase.showindices(io::IO, ind1::IdOffsetRange, inds::IdOffsetRange...) = Base.showindices(io, map(UnitRange, (ind1, inds...))...)\n\nfunction Base.showarg(io::IO, @nospecialize(a::OffsetArray), toplevel)\n    print(io, \"OffsetArray(\")\n    Base.showarg(io, parent(a), false)\n    Base.showindices(io, axes(a)...)\n    print(io, ')')\n    if toplevel\n        print(io, \" with eltype \", eltype(a))\n    end\nend\n\nfunction Base.replace_in_print_matrix(A::OffsetArray{<:Any,2}, i::Integer, j::Integer, s::AbstractString)\n    J = map(parentindex, axes(A), (i,j))\n    Base.replace_in_print_matrix(parent(A), J..., s)\nend\nfunction Base.replace_in_print_matrix(A::OffsetArray{<:Any,1}, i::Integer, j::Integer, s::AbstractString)\n    ip = parentindex(axes(A,1), i)\n    Base.replace_in_print_matrix(parent(A), ip, j, s)\nend\n\n# Actual unsafe_wrap implementation\n@inline function _unsafe_wrap(pointer::Ptr{T}, inds::NTuple{N, OffsetAxisKnownLength}; own = false, kw...) where {T,N}\n    _checkindices(N, inds, \"indices\")\n    AA = Base.unsafe_wrap(Array, pointer, map(_indexlength, inds); own=own)\n    OffsetArray{T, N, typeof(AA)}(AA, map(_indexoffset, inds); kw...)\nend\nconst OffsetArrayUnion{T,N} = Union{Type{OffsetArray}, Type{OffsetArray{T}}, Type{OffsetArray{T,N}}, Type{OffsetArray{T1, N} where T1}} where {T,N}\n\n\"\"\"\n    Base.unsafe_wrap(OffsetArray, pointer::Ptr{T}, inds...; own=false, kw...)\n    Base.unsafe_wrap(OffsetArray, pointer::Ptr{T}, inds::Tuple; own=false, kw...)\n\nConstruct an `OffsetArray` around a pointer with axes defined by `inds` which may be Integers or AbstractUnitRanges.\nIf the keyword `own` is true, then Julia will free the pointer when the array is garbage collected.\nOther keywords are forwarded to the `OffsetArray` constructor.\n\"\"\"\n@inline function Base.unsafe_wrap(::OffsetArrayUnion{T,N}, pointer::Ptr{T}, inds::NTuple{N, OffsetAxisKnownLength}; kw...) where {T,N}\n    _unsafe_wrap(pointer, inds; kw...)\nend\n# Avoid ambiguity\n@inline function Base.unsafe_wrap(::OffsetArrayUnion{T,N}, pointer::Ptr{T}, inds::NTuple{N, <:Integer}; kw...) where {T,N}\n    _unsafe_wrap(pointer, inds; kw...)\nend\n@inline function Base.unsafe_wrap(::OffsetArrayUnion{T,N}, pointer::Ptr{T}, inds::Vararg{OffsetAxisKnownLength,N}; kw...) where {T,N}\n    _unsafe_wrap(pointer, inds; kw...)\nend\n# Avoid ambiguity\n@inline function Base.unsafe_wrap(::OffsetArrayUnion{T,N}, pointer::Ptr{T}, inds::Vararg{Integer,N}; kw...) where {T,N}\n    _unsafe_wrap(pointer, inds; kw...)\nend\n\n\"\"\"\n    no_offset_view(A)\n\nReturn an `AbstractArray` that shares structure and underlying data with the argument,\nbut uses 1-based indexing. May just return the argument when applicable.\nNot exported.\n\nThe default implementation uses `OffsetArrays`, but other types should use something more\nspecific to remove a level of indirection when applicable.\n\n```jldoctest; setup=:(using OffsetArrays)\njulia> A = [1 3 5; 2 4 6];\n\njulia> O = OffsetArray(A, 0:1, -1:1)\n2×3 OffsetArray(::$(Matrix{Int}), 0:1, -1:1) with eltype $Int with indices 0:1×-1:1:\n 1  3  5\n 2  4  6\n\njulia> OffsetArrays.no_offset_view(O)[1,1] = -9\n-9\n\njulia> A\n2×3 $(Matrix{Int}):\n -9  3  5\n  2  4  6\n```\n\"\"\"\nno_offset_view(A::OffsetArray) = no_offset_view(parent(A))\nif isdefined(Base, :IdentityUnitRange)\n    # valid only if Slice is distinguished from IdentityUnitRange\n    _onebasedslice(S::Base.Slice) = Base.Slice(Base.OneTo(length(S)))\n    _onebasedslice(S::Base.Slice{<:Base.OneTo}) = S\n    _onebasedslice(S) = S\n    _isoffsetslice(::Any) = false\n    _isoffsetslice(::Base.Slice) = true\n    _isoffsetslice(::Base.Slice{<:Base.OneTo}) = false\n    function no_offset_view(S::SubArray)\n        #= If a view contains an offset Slice axis,\n        i.e. it is a view of an offset array along the offset axis,\n        we shift the axis to a 1-based one.\n        E.g. Slice(2:3) -> Slice(Base.OneTo(2))\n        We transform the `parent` as well as the `parentindices`,\n        so that the view still points to the same elements, even though the indices have changed.\n        This way, we retain the axis of the view as a `Slice`\n        =#\n        P = parent(S)\n        pinds = parentindices(S)\n        #=\n        Check if all the axes are `Slice`s and the parent has `OneTo` axes,\n        in which case we may unwrap the `OffsetArray` and forward the view to the parent.\n        =#\n        may_pop_parent = all(_isoffsetslice, pinds) && P isa OffsetArray && all(x -> x isa Base.OneTo, axes(parent(P)))\n        if may_pop_parent\n            return no_offset_view(P)\n        end\n        #=\n        we convert offset `Slice`s to 1-based ones using `_onebasedslice`.\n        The next call, `no_offset_view`, is a no-op on a `Slice{<:OneTo}`,\n        while it converts the offset axes to 1-based ones.\n        Eventually, we end up with a `Tuple` comprising `Slice{<:OneTo}`s and other 1-based axes.\n\n        The difference between `_onebasedslice` and `no_offset_view` is that\n        the latter does not change the value of the range, while the former does.\n        =#\n        newviewinds = map(no_offset_view ∘ _onebasedslice, pinds)\n        needs_shifting = any(_isoffsetslice, pinds)\n        P_maybeshiftedinds = if needs_shifting\n            t = Origin(parent(S)).index\n            neworigin = ntuple(i -> _isoffsetslice(pinds[i]) ? 1 : t[i], length(t))\n            Origin(neworigin)(P)\n        else\n            P\n        end\n        view(P_maybeshiftedinds, newviewinds...)\n    end\nend\nno_offset_view(a::Array) = a\nno_offset_view(i::Number) = i\nno_offset_view(A::AbstractArray) = _no_offset_view(axes(A), A)\n_no_offset_view(::Tuple{}, A::AbstractArray{T,0}) where T = A\n_no_offset_view(::Tuple{Base.OneTo, Vararg{Base.OneTo}}, A::AbstractArray) = A\n_no_offset_view(::Any, A::AbstractArray) = _no_offset_view(A)\n_no_offset_view(A::AbstractArray) = OffsetArray(A, Origin(1))\n_no_offset_view(A::AbstractUnitRange) = UnitRange(A)\n\n#####\n# center/centered\n# These two helpers are deliberately not exported; their meaning can be very different in\n# other scenarios and will be very likely to cause name conflicts if exported.\n#####\n\nif VERSION < v\"1.4\"\n   _halfroundInt(v, r::RoundingMode) = round(Int, v/2, r)\nelse\n   _halfroundInt(v, r::RoundingMode) = div(v, 2, r)\nend\n\n\"\"\"\n    center(A, [r::RoundingMode=RoundDown])::Dims\n\nReturn the center coordinate of given array `A`. If `size(A, k)` is even,\na rounding procedure will be applied with mode `r`.\n\n!!! compat \"OffsetArrays 1.9\"\n    This method requires at least OffsetArrays 1.9.\n\n# Examples\n\n```jldoctest; setup=:(using OffsetArrays)\njulia> A = reshape(collect(1:9), 3, 3)\n3×3 $(Matrix{Int}):\n 1  4  7\n 2  5  8\n 3  6  9\n\njulia> c = OffsetArrays.center(A)\n(2, 2)\n\njulia> A[c...]\n5\n\njulia> Ao = OffsetArray(A, -2, -2); # axes (-1:1, -1:1)\n\njulia> c = OffsetArrays.center(Ao)\n(0, 0)\n\njulia> Ao[c...]\n5\n```\n\nTo shift the center coordinate of the given array to `(0, 0, ...)`, you\ncan use [`centered`](@ref OffsetArrays.centered).\n\"\"\"\nfunction center(A::AbstractArray, r::RoundingMode=RoundDown)\n    map(axes(A)) do inds\n        _halfroundInt(length(inds)-1, r) + first(inds)\n    end\nend\n\n\"\"\"\n    centered(A, cp=center(A)) -> Ao\n\nShift the center coordinate/point `cp` of array `A` to `(0, 0, ..., 0)`. Internally, this is\nequivalent to `OffsetArray(A, .-cp)`.\n\n!!! compat \"OffsetArrays 1.9\"\n    This method requires at least OffsetArrays 1.9.\n\n# Examples\n\n```jldoctest; setup=:(using OffsetArrays)\njulia> A = reshape(collect(1:9), 3, 3)\n3×3 $(Matrix{Int}):\n 1  4  7\n 2  5  8\n 3  6  9\n\njulia> Ao = OffsetArrays.centered(A); # axes (-1:1, -1:1)\n\njulia> Ao[0, 0]\n5\n\njulia> Ao = OffsetArray(A, OffsetArrays.Origin(0)); # axes (0:2, 0:2)\n\njulia> Aoo = OffsetArrays.centered(Ao); # axes (-1:1, -1:1)\n\njulia> Aoo[0, 0]\n5\n```\n\nUsers are allowed to pass `cp` to change how \"center point\" is interpreted, but the meaning of the\noutput array should be reinterpreted as well. For instance, if `cp = map(last, axes(A))` then this\nfunction no longer shifts the center point but instead the bottom-right point to `(0, 0, ..., 0)`.\nA commonly usage of `cp` is to change the rounding behavior when the array is of even size at some\ndimension:\n\n```jldoctest; setup=:(using OffsetArrays)\njulia> A = reshape(collect(1:4), 2, 2) # Ideally the center should be (1.5, 1.5) but OffsetArrays only support integer offsets\n2×2 $(Matrix{Int}):\n 1  3\n 2  4\n\njulia> OffsetArrays.centered(A, OffsetArrays.center(A, RoundUp)) # set (2, 2) as the center point\n2×2 OffsetArray(::$(Matrix{Int}), -1:0, -1:0) with eltype $(Int) with indices -1:0×-1:0:\n 1  3\n 2  4\n\njulia> OffsetArrays.centered(A, OffsetArrays.center(A, RoundDown)) # set (1, 1) as the center point\n2×2 OffsetArray(::$(Matrix{Int}), 0:1, 0:1) with eltype $(Int) with indices 0:1×0:1:\n 1  3\n 2  4\n```\n\nSee also [`center`](@ref OffsetArrays.center).\n\"\"\"\ncentered(A::AbstractArray, cp::Dims=center(A)) = OffsetArray(A, .-cp)\n\ncentered(A::AbstractArray, i::CartesianIndex) = centered(A, Tuple(i))\n\nif VERSION < v\"1.12.0-DEV.1713\"\n    # The Base implementations are fixed in https://github.com/JuliaLang/julia/pull/56464 and https://github.com/JuliaLang/julia/pull/56474\n    # we therefore limit these specializations to older versions of julia\n\n    # we may pass the searchsorted* functions to the parent, and wrap the offset\n    for f in [:searchsortedfirst, :searchsortedlast, :searchsorted]\n        _safe_f = Symbol(\"_safe_\" * String(f))\n        @eval function $_safe_f(v::OffsetVector, x, ilo, ihi, o::Base.Ordering)\n            offset = v.offsets[1]\n            $f(parent(v), x, ilo - offset, ihi - offset, o) .+ offset\n        end\n        @eval Base.$f(v::OffsetVector, x, ilo::T, ihi::T, o::Base.Ordering) where T<:Integer =\n            $_safe_f(v, x, ilo, ihi, o)\n    end\n\n    if VERSION <= v\"1.2\"\n        # ambiguity warnings in earlier versions\n        for f in [:searchsortedfirst, :searchsortedlast, :searchsorted]\n            _safe_f = Symbol(\"_safe_\" * String(f))\n            @eval Base.$f(v::OffsetVector, x, ilo::Int, ihi::Int, o::Base.Ordering) =\n                $_safe_f(v, x, ilo, ihi, o)\n        end\n    end\nend\n\nif VERSION < v\"1.1.0-DEV.783\"\n    Base.copyfirst!(dest::OffsetArray, src::OffsetArray) = (maximum!(parent(dest), parent(src)); return dest)\nend\n\nif VERSION <= v\"1.7.0-DEV.400\"\n    # https://github.com/JuliaLang/julia/pull/39393\n    # index for zero-argument getindex should be first linear index instead of 1 (#194)\n    Base._to_linear_index(A::OffsetArray) = first(LinearIndices(A))\nend\n\nif !isdefined(Base, :get_extension)\n  include(\"../ext/OffsetArraysAdaptExt.jl\")\nend\n\nif Base.VERSION >= v\"1.4.2\"\n    include(\"precompile.jl\")\n    _precompile_()\nend\n\n\n##\n# Deprecations\n##\n\n# This is a bad API design as it introduces counter intuitive results (#250)\n@deprecate centered(A::AbstractArray, r::RoundingMode) OffsetArray(A, .-center(A, r)) false\n\nend # module\n"
  },
  {
    "path": "src/axes.jl",
    "content": "\"\"\"\n    ro = IdOffsetRange(r::AbstractUnitRange, offset=0)\n\nConstruct an \"identity offset range\". Numerically, `collect(ro) == collect(r) .+ offset`,\nwith the additional property that `axes(ro, 1) = axes(r, 1) .+ offset`.\nWhen `r` starts at 1, then `ro[i] == i` and even `ro[ro] == ro`,\ni.e., it's the \"identity,\" which is the origin of the \"Id\" in `IdOffsetRange`.\n\n# Examples\n\nThe most common case is shifting a range that starts at 1 (either `1:n` or `Base.OneTo(n)`):\n```jldoctest ior\njulia> using OffsetArrays: IdOffsetRange\n\njulia> ro = IdOffsetRange(1:3, -2)\nIdOffsetRange(values=-1:1, indices=-1:1)\n\njulia> axes(ro, 1)\nIdOffsetRange(values=-1:1, indices=-1:1)\n\njulia> ro[-1]\n-1\n\njulia> ro[3]\nERROR: BoundsError: attempt to access 3-element $(IdOffsetRange{Int, UnitRange{Int}}) with indices -1:1 at index [3]\n```\n\nIf the range doesn't start at 1, the values may be different from the indices:\n```jldoctest ior\njulia> ro = IdOffsetRange(11:13, -2)\nIdOffsetRange(values=9:11, indices=-1:1)\n\njulia> axes(ro, 1)     # 11:13 is indexed by 1:3, and the offset is also applied to the axes\nIdOffsetRange(values=-1:1, indices=-1:1)\n\njulia> ro[-1]\n9\n\njulia> ro[3]\nERROR: BoundsError: attempt to access 3-element $(IdOffsetRange{Int, UnitRange{Int}}) with indices -1:1 at index [3]\n```\n\n# Extended help\n\nConstruction/coercion preserves the (shifted) values of the input range, but may modify\nthe indices if required by the specified types. For example,\n\n    r = OffsetArrays.IdOffsetRange{Int,UnitRange{Int}}(3:4)\n\nhas `r[1] == 3` and `r[2] == 4`, whereas\n\n    r = OffsetArrays.IdOffsetRange{Int,Base.OneTo{Int}}(3:4)\n\nhas `r[3] == 3` and `r[4] == 4`, and `r[1]` would throw a `BoundsError`.\nIn this latter case, a shift in the axes was needed because `Base.OneTo` ranges\nmust start with value 1.\n\n!!! warning\n\n    In the future, *conversion* will preserve both the values and\n    the indices, throwing an error when this is not achievable. For instance,\n\n        r = convert(OffsetArrays.IdOffsetRange{Int,UnitRange{Int}}, 3:4)\n\n    has `r[1] == 3` and `r[2] == 4` and would satisfy `r == 3:4`, whereas\n\n    ```julia\n    julia> convert(OffsetArrays.IdOffsetRange{Int,Base.OneTo{Int}}, 3:4)    # future behavior, not present behavior\n    ERROR: ArgumentError: first element must be 1, got 3\n    ```\n\n    where the error will arise because the result could not have the same axes as the input.\n\n    An important corollary is that `typeof(r1)(r2)` and `oftype(r1, r2)` will behave differently:\n    the first coerces `r2` to be of the type of `r1`, whereas the second converts.\n    Developers are urged to future-proof their code by choosing the behavior appropriate for each usage.\n\"\"\"\nstruct IdOffsetRange{T<:Integer,I<:AbstractUnitRange{T}} <: AbstractUnitRange{T}\n    parent::I\n    offset::T\n\n    function IdOffsetRange{T,I}(r::I, offset::T) where {T<:Integer,I<:AbstractUnitRange{T}}\n        _bool_check(T, r, offset)\n        new{T,I}(r, offset)\n    end\n\n    #= This method is necessary to avoid a StackOverflowError in IdOffsetRange{T,I}(r::IdOffsetRange, offset::Integer).\n    The type signature in that method is more specific than IdOffsetRange{T,I}(r::I, offset::T),\n    so it ends up calling itself if I <: IdOffsetRange.\n    =#\n    function IdOffsetRange{T,IdOffsetRange{T,I}}(r::IdOffsetRange{T,I}, offset::T) where {T<:Integer,I<:AbstractUnitRange{T}}\n        _bool_check(T, r, offset)\n        new{T,IdOffsetRange{T,I}}(r, offset)\n    end\nend\n\nfunction _bool_check(::Type{Bool}, r, offset)\n    # disallow the construction of IdOffsetRange{Bool, UnitRange{Bool}}(true:true, true)\n    if offset && (first(r) || last(r))\n        throw(ArgumentError(\"values = $r and offset = $offset can not produce a boolean range\"))\n    end\n    return nothing\nend\n_bool_check(::Type, r, offset) = nothing\n\n# Construction/coercion from arbitrary AbstractUnitRanges\nfunction IdOffsetRange{T,I}(r::AbstractUnitRange, offset::Integer = 0) where {T<:Integer,I<:AbstractUnitRange{T}}\n    rc, o = offset_coerce(I, r)\n    return IdOffsetRange{T,I}(rc, convert(T, o+offset)::T)\nend\nfunction IdOffsetRange{T}(r::AbstractUnitRange, offset::Integer = 0) where T<:Integer\n    rc = convert(AbstractUnitRange{T}, r)::AbstractUnitRange{T}\n    return IdOffsetRange{T,typeof(rc)}(rc, convert(T, offset)::T)\nend\nIdOffsetRange(r::AbstractUnitRange{T}, offset::Integer = 0) where T<:Integer =\n    IdOffsetRange{T,typeof(r)}(r, convert(T, offset)::T)\n\n# Coercion from other IdOffsetRanges\nIdOffsetRange{T,I}(r::IdOffsetRange{T,I}) where {T<:Integer,I<:AbstractUnitRange{T}} = r\nfunction IdOffsetRange{T,I}(r::IdOffsetRange, offset::Integer = 0) where {T<:Integer,I<:AbstractUnitRange{T}}\n    rc, offset_rc = offset_coerce(I, r.parent)\n    return IdOffsetRange{T,I}(rc, convert(T, r.offset + offset + offset_rc)::T)\nend\nIdOffsetRange{T}(r::IdOffsetRange{T}) where {T<:Integer} = r\nfunction IdOffsetRange{T}(r::IdOffsetRange, offset::Integer = 0) where T<:Integer\n    return IdOffsetRange{T}(r.parent, r.offset + offset)\nend\nIdOffsetRange(r::IdOffsetRange) = r\n\n# Constructor to make `show` round-trippable\n# try to preserve typeof(values) if the indices are known to be 1-based\n_subtractindexoffset(values, indices::Union{Base.OneTo, IdentityUnitRange{<:Base.OneTo}}, offset) = values\n_subtractindexoffset(values, indices, offset) = _subtractoffset(values, offset)\nfunction IdOffsetRange(; values::AbstractUnitRange{<:Integer}, indices::AbstractUnitRange{<:Integer})\n    length(values) == length(indices) || throw(ArgumentError(\"values and indices must have the same length\"))\n    values_nooffset = no_offset_view(values)\n    offset = first(indices) - 1\n    values_minus_offset = _subtractindexoffset(values_nooffset, indices, offset)\n    return IdOffsetRange(values_minus_offset, offset)\nend\n\n# Conversions to an AbstractUnitRange{Int} (and to an OrdinalRange{Int,Int} on Julia v\"1.6\") are necessary\n# to evaluate CartesianIndices for BigInt ranges, as their axes are also BigInt ranges\nBase.AbstractUnitRange{T}(r::IdOffsetRange) where {T<:Integer} = IdOffsetRange{T}(r)\n\n# https://github.com/JuliaLang/julia/pull/40038\nif v\"1.6\" <= VERSION < v\"1.9.0-DEV.642\"\n    Base.OrdinalRange{T,T}(r::IdOffsetRange) where {T<:Integer} = IdOffsetRange{T}(r)\nend\n\n# TODO: uncomment these when Julia is ready\n# # Conversion preserves both the values and the indices, throwing an InexactError if this\n# # is not possible.\n# Base.convert(::Type{IdOffsetRange{T,I}}, r::IdOffsetRange{T,I}) where {T<:Integer,I<:AbstractUnitRange{T}} = r\n# Base.convert(::Type{IdOffsetRange{T,I}}, r::IdOffsetRange) where {T<:Integer,I<:AbstractUnitRange{T}} =\n#     IdOffsetRange{T,I}(convert(I, r.parent), r.offset)\n# Base.convert(::Type{IdOffsetRange{T,I}}, r::AbstractUnitRange) where {T<:Integer,I<:AbstractUnitRange{T}} =\n#     IdOffsetRange{T,I}(convert(I, r), 0)\n\noffset_coerce(::Type{Base.OneTo{T}}, r::Base.OneTo) where T<:Integer = convert(Base.OneTo{T}, r), 0\nfunction offset_coerce(::Type{Base.OneTo{T}}, r::AbstractUnitRange) where T<:Integer\n    o = first(r) - 1\n    return Base.OneTo{T}(last(r) - o), o\nend\n# function offset_coerce(::Type{Base.OneTo{T}}, r::IdOffsetRange) where T<:Integer\n#     rc, o = offset_coerce(Base.OneTo{T}, r.parent)\n\n# Fallback, specialze this method if `convert(I, r)` doesn't do what you need\noffset_coerce(::Type{I}, r::AbstractUnitRange) where I<:AbstractUnitRange =\n    convert(I, r)::I, 0\n\n@inline Base.parent(r::IdOffsetRange) = r.parent\n@inline Base.axes(r::IdOffsetRange) = (axes1(r),)\n@inline axes1(r::IdOffsetRange) = IdOffsetRange(Base.axes1(r.parent), r.offset)\nif VERSION < v\"1.8.2\"\n    Base.axes1(r::IdOffsetRange) = axes1(r)\nend\n@inline Base.unsafe_indices(r::IdOffsetRange) = (axes1(r),)\n@inline Base.length(r::IdOffsetRange) = length(r.parent)\n@inline Base.isempty(r::IdOffsetRange) = isempty(r.parent)\n#= We specialize on reduced_indices to work around cases where the parent axis type doesn't\nsupport reduced_index, but the axes do support reduced_indices\nThe difference is that reduced_index expects the axis type to remain unchanged,\nwhich may not always be possible, eg. for statically sized axes\nSee https://github.com/JuliaArrays/OffsetArrays.jl/issues/204\n=#\nfunction Base.reduced_indices(inds::Tuple{IdOffsetRange, Vararg{IdOffsetRange}}, d::Int)\n    parents_reduced = Base.reduced_indices(map(parent, inds), d)\n    ntuple(i -> IdOffsetRange(parents_reduced[i], inds[i].offset), Val(length(inds)))\nend\nBase.reduced_index(i::IdOffsetRange) = typeof(i)(first(i):first(i))\n# Workaround for #92 on Julia < 1.4\nBase.reduced_index(i::IdentityUnitRange{<:IdOffsetRange}) = typeof(i)(first(i):first(i))\nif VERSION < v\"1.8.2\"\n    for f in [:firstindex, :lastindex]\n        @eval @inline Base.$f(r::IdOffsetRange) = $f(r.parent) + r.offset\n    end\nend\nfor f in [:first, :last]\n    # coerce the type to deal with values that get promoted on addition (eg. Bool)\n    @eval @inline Base.$f(r::IdOffsetRange) = eltype(r)($f(r.parent) + r.offset)\nend\n\n# Iteration for an IdOffsetRange\n@inline Base.iterate(r::IdOffsetRange, i...) = _iterate(r, i...)\n# In general we iterate over the parent term by term and add the offset.\n# This might have some performance degradation when coupled with bounds-checking\n# See https://github.com/JuliaArrays/OffsetArrays.jl/issues/214\n@inline function _iterate(r::IdOffsetRange, i...)\n    ret = iterate(r.parent, i...)\n    ret === nothing && return nothing\n    return (eltype(r)(ret[1] + r.offset), ret[2])\nend\n# Base.OneTo(n) is known to be exactly equivalent to the range 1:n,\n# and has no specialized iteration defined for it,\n# so we may add the offset to the range directly and iterate over the result\n# This gets around the performance issue described in issue #214\n# We use the helper function _addoffset to evaluate the range instead of broadcasting\n# just in case this makes it easy for the compiler.\n@inline _iterate(r::IdOffsetRange{<:Integer, <:Base.OneTo}, i...) = iterate(_addoffset(r.parent, r.offset), i...)\n\n@inline function Base.getindex(r::IdOffsetRange, i::Integer)\n    i isa Bool && throw(ArgumentError(\"invalid index: $i of type Bool\"))\n    @boundscheck checkbounds(r, i)\n    @inbounds eltype(r)(r.parent[i - r.offset] + r.offset)\nend\n\n# Logical indexing following https://github.com/JuliaLang/julia/pull/31829\n#= Helper function to perform logical indxeing for boolean ranges\nThe code implemented is a branch-free version of the following:\n\n    range(first(s) ? first(r) : last(r), length=Int(last(s)))\n\nSee https://github.com/JuliaArrays/OffsetArrays.jl/pull/224#discussion_r595635143\n\nLogical indexing does not preserve indices, unlike other forms of vector indexing\n=#\n@inline function _getindex(r, s::AbstractUnitRange{Bool})\n    range(first(r) * first(s) + last(r) * !first(s), length=Int(last(s)))\nend\n@inline function _getindex(r, s::StepRange{Bool})\n    range(first(r) * first(s) + last(r) * !first(s), step = oneunit(step(s)), length=Int(last(s)))\nend\n@inline function _getindex(r, s::AbstractUnitRange)\n    @inbounds rs = r.parent[_subtractoffset(s, r.offset)] .+ r.offset\n    _indexedby(rs, axes(s))\nend\n@inline function _getindex(r, s::StepRange)\n    rs = @inbounds r.parent[s .- r.offset] .+ r.offset\n    _indexedby(rs, axes(s))\nend\n\nfor T in [:AbstractUnitRange, :StepRange]\n    @eval @inline function Base.getindex(r::IdOffsetRange, s::$T{<:Integer})\n        @boundscheck checkbounds(r, s)\n        return _getindex(r, s)\n    end\nend\n\n# These methods are necessary to avoid ambiguity\nfor R in [:IIUR, :IdOffsetRange]\n    @eval @inline function Base.getindex(r::IdOffsetRange, s::$R)\n        @boundscheck checkbounds(r, s)\n        return _getindex(r, s)\n    end\nend\n\n# offset-preserve broadcasting\nBroadcast.broadcasted(::Base.Broadcast.DefaultArrayStyle{1}, ::typeof(-), r::IdOffsetRange, x::Integer) =\n    IdOffsetRange(r.parent .- x, r.offset)\nBroadcast.broadcasted(::Base.Broadcast.DefaultArrayStyle{1}, ::typeof(+), r::IdOffsetRange, x::Integer) =\n    IdOffsetRange(r.parent .+ x, r.offset)\nBroadcast.broadcasted(::Base.Broadcast.DefaultArrayStyle{1}, ::typeof(+), x::Integer, r::IdOffsetRange) =\n    IdOffsetRange(x .+ r.parent, r.offset)\nBroadcast.broadcasted(::Base.Broadcast.DefaultArrayStyle{1}, ::typeof(big), r::IdOffsetRange) =\n    IdOffsetRange(big.(r.parent), r.offset)\n\nBase.show(io::IO, r::IdOffsetRange) = print(io, IdOffsetRange, \"(values=\",first(r), ':', last(r),\", indices=\",first(eachindex(r)),':',last(eachindex(r)), \")\")\n\n# Optimizations\n@inline Base.checkindex(::Type{Bool}, inds::IdOffsetRange, i::Real) = Base.checkindex(Bool, inds.parent, i - inds.offset)\n\nif VERSION < v\"1.5.2\"\n    # issue 100, 133: IdOffsetRange as another index-preserving case shouldn't comtribute offsets\n    # fixed by https://github.com/JuliaLang/julia/pull/37204\n    @inline Base.compute_offset1(parent, stride1::Integer, dims::Tuple{Int}, inds::Tuple{IdOffsetRange}, I::Tuple) =\n        Base.compute_linindex(parent, I) - stride1*first(Base.axes1(inds[1]))\nend\n\n# This was deemed \"too private\" to extend: see issue #184\n# # Fixes an inference failure in Base.mapfirst!\n# # Test: A = OffsetArray(rand(4,4), (-3,5)); R = similar(A, (1:1, 6:9)); maximum!(R, A)\n# if isdefined(Base, :_firstslice)\n#     Base._firstslice(i::IdOffsetRange) = IdOffsetRange(Base._firstslice(i.parent), i.offset)\n# end\n"
  },
  {
    "path": "src/origin.jl",
    "content": "\"\"\"\n    Origin(indices...)\n    Origin(origin::Tuple)\n    Origin(origin::CartesianIndex)\n\nA helper type to construct OffsetArray with a given origin. This is not exported.\n\nThe `origin` of an array is defined as the tuple of the first index along each axis, i.e., `first.(axes(A))`.\n\n# Example\n\n```jldoctest origin; setup=:(using OffsetArrays)\njulia> a = [1 2; 3 4];\n\njulia> using OffsetArrays: Origin\n\njulia> OffsetArray(a, Origin(0, 1))\n2×2 OffsetArray(::$(Array{Int,2}), 0:1, 1:2) with eltype $Int with indices 0:1×1:2:\n 1  2\n 3  4\n\njulia> OffsetArray(a, Origin(0)) # short notation for `Origin(0, 0)`\n2×2 OffsetArray(::$(Array{Int, 2}), 0:1, 0:1) with eltype $Int with indices 0:1×0:1:\n 1  2\n 3  4\n```\n\nAn `Origin` object is callable, and it may shift the origin of an array to the specified point.\n\n```jldoctest origin\njulia> b = Origin(0)(a) # shift the origin of the array to (0,0)\n2×2 OffsetArray(::$(Array{Int, 2}), 0:1, 0:1) with eltype $Int with indices 0:1×0:1:\n 1  2\n 3  4\n```\n\nThe type `Origin`, when called with an `AbstractArray` as the argument, will return an instance\ncorresponding ot the origin of the array.\n\n```jldoctest origin\njulia> origin_b = Origin(b) # retrieve the origin of the array as an Origin instance\nOrigin(0, 0)\n\njulia> origin_b(ones(2,2)) # shift the origin of another array to that of b, in this case to (0,0)\n2×2 OffsetArray(::$(Array{Float64, 2}), 0:1, 0:1) with eltype Float64 with indices 0:1×0:1:\n 1.0  1.0\n 1.0  1.0\n```\n\n!!! tip\n    One may broadcast an `Origin` instance over multiple arrays to shift them all to the same origin.\n    ```jldoctest\n    julia> using OffsetArrays: Origin\n\n    julia> a = [1 2; 3 4]; # origin at (1,1)\n\n    julia> b = Origin(2,3)(a); # origin at (2,3)\n\n    julia> c = Origin(4)(a); # origin at (4,4)\n\n    julia> ao, bo, co = Origin(0).((a, b, c)); # shift all origins to (0,0)\n\n    julia> first.(axes(ao)) == first.(axes(bo)) == first.(axes(co)) == (0,0)\n    true\n\n    julia> ao, bo, co = Origin(b).((a, b, c)); # shift all origins to that of b\n\n    julia> first.(axes(ao)) == first.(axes(bo)) == first.(axes(co)) == (2,3)\n    true\n\n    julia> ao, bo, co = OffsetArray.((a, b, c), Origin(b)); # another way to do the same\n\n    julia> first.(axes(ao)) == first.(axes(bo)) == first.(axes(co)) == (2,3)\n    true\n    ```\n\"\"\"\nstruct Origin{T<:Union{Tuple{Vararg{Int}}, Int}}\n    index::T\nend\nOrigin(I::Tuple{Vararg{Int}}) = Origin{typeof(I)}(I)\nOrigin(I::Tuple{Vararg{Number}}) = Origin(map(Int, I))\nOrigin(I::CartesianIndex) = Origin(Tuple(I))\nOrigin(I::Number...) = Origin(I)\n# Origin(0) != Origin((0, )) but they work the same with broadcasting\nOrigin(n::Number) = Origin{Int}(Int(n))\n\nBase.Broadcast.broadcastable(o::Origin) = Ref(o)\n\n_showidx(index::Integer) = \"(\" * string(index) * \")\"\n_showidx(index::Tuple) = string(index)\nBase.show(io::IO, o::Origin) = print(io, \"Origin\", _showidx(o.index))\n"
  },
  {
    "path": "src/precompile.jl",
    "content": "function _precompile_()\n    ccall(:jl_generating_output, Cint, ()) == 1 || return nothing\n    Base.precompile(Tuple{typeof(Base.showarg),IOBuffer,OffsetArray{Int, 0, Array{Int, 0}},Bool})   # time: 0.037824474\n    Base.precompile(Tuple{Type{IdOffsetRange{Int, Base.OneTo{Int}}},UnitRange{Int}})   # time: 0.009825722\n    Base.precompile(Tuple{typeof(Base.inds2string),Tuple{IdOffsetRange{Int, Base.OneTo{Int}}, IdOffsetRange{Int, Base.OneTo{Int}}}})   # time: 0.0080779\n    Base.precompile(Tuple{typeof(zeros),Tuple{IdOffsetRange{Int, Base.OneTo{Int}}}})   # time: 0.007713056\n    Base.precompile(Tuple{typeof(ones),Tuple{IdOffsetRange{Int, Base.OneTo{Int}}}})   # time: 0.007713056\n    Base.precompile(Tuple{typeof(trues),Tuple{UnitRange{Int}, UnitRange{Int}}})   # time: 0.005478372\n    Base.precompile(Tuple{typeof(falses),Tuple{UnitRange{Int}, UnitRange{Int}}})   # time: 0.005478372\n    Base.precompile(Tuple{typeof(firstindex),IdOffsetRange{Int, Base.OneTo{Int}}})   # time: 0.004100289\nend\n"
  },
  {
    "path": "src/utils.jl",
    "content": "### Low-level utilities ###\n\n_indexoffset(r::AbstractRange) = first(r) - 1\n_indexoffset(i::Integer) = 0\n_indexlength(r::AbstractRange) = length(r)\n_indexlength(i::Integer) = Int(i)\n_indexlength(i::Colon) = Colon()\n\n# utility methods used in reshape\n# we don't use _indexlength in this to avoid converting the arguments to Int\n_checksize(ind::Integer, s) = ind == s\n_checksize(ind::AbstractUnitRange, s) = length(ind) == s\n\n_toaxis(i::Integer) = Base.OneTo(i)\n_toaxis(i) = i\n\n_strip_IdOffsetRange(r::IdOffsetRange) = parent(r)\n_strip_IdOffsetRange(r) = r\n\n_offset(axparent::AbstractUnitRange, ax::AbstractUnitRange) = first(ax) - first(axparent)\n_offset(axparent::AbstractUnitRange, ::Union{Integer, Colon}) = 1 - first(axparent)\n\n_offsets(A::AbstractArray) = map(ax -> first(ax) - 1, axes(A))\n_offsets(A::AbstractArray, B::AbstractArray) = map(_offset, axes(B), axes(A))\n\n\"\"\"\n    OffsetArrays.AxisConversionStyle(typeof(indices))\n\n`AxisConversionStyle` declares if `indices` should be converted to a single `AbstractUnitRange{Int}`\nor to a `Tuple{Vararg{AbstractUnitRange{Int}}}` while flattening custom types into indices.\nThis method is called after `to_indices(A::Array, axes(A), indices)` to provide\nfurther information in case `to_indices` does not return a `Tuple` of `AbstractUnitRange{Int}`.\n\nCustom index types should extend `AxisConversionStyle` and return either `OffsetArray.SingleRange()`,\nwhich is the default, or `OffsetArray.TupleOfRanges()`. In the former case, the type `T` should\ndefine `Base.convert(::Type{AbstractUnitRange{Int}}, ::T)`, whereas in the latter it should define\n`Base.convert(::Type{Tuple{Vararg{AbstractUnitRange{Int}}}}, ::T)`.\n\nAn example of the latter is `CartesianIndices`, which is converted to a `Tuple` of\n`AbstractUnitRange{Int}` while flattening the indices.\n\n# Example\n```jldoctest; setup=:(using OffsetArrays)\njulia> struct NTupleOfUnitRanges{N}\n           x ::NTuple{N, UnitRange{Int}}\n       end\n\njulia> Base.to_indices(A, inds, t::Tuple{NTupleOfUnitRanges{N}}) where {N} = t;\n\njulia> OffsetArrays.AxisConversionStyle(::Type{NTupleOfUnitRanges{N}}) where {N} = OffsetArrays.TupleOfRanges();\n\njulia> Base.convert(::Type{Tuple{Vararg{AbstractUnitRange{Int}}}}, t::NTupleOfUnitRanges) = t.x;\n\njulia> a = zeros(3, 3);\n\njulia> inds = NTupleOfUnitRanges((3:5, 2:4));\n\njulia> oa = OffsetArray(a, inds);\n\njulia> axes(oa, 1) == 3:5\ntrue\n\njulia> axes(oa, 2) == 2:4\ntrue\n```\n\"\"\"\nabstract type AxisConversionStyle end\nstruct SingleRange <: AxisConversionStyle end\nstruct TupleOfRanges <: AxisConversionStyle end\n\nAxisConversionStyle(::Type) = SingleRange()\nAxisConversionStyle(::Type{<:CartesianIndices}) = TupleOfRanges()\n\n_convertTupleAbstractUnitRange(x) = _convertTupleAbstractUnitRange(AxisConversionStyle(typeof(x)), x)\n_convertTupleAbstractUnitRange(::SingleRange, x) = (convert(AbstractUnitRange{Int}, x),)\n_convertTupleAbstractUnitRange(::TupleOfRanges, x) = convert(Tuple{Vararg{AbstractUnitRange{Int}}}, x)\n\n_toAbstractUnitRanges(t::Tuple) = (_convertTupleAbstractUnitRange(first(t))..., _toAbstractUnitRanges(tail(t))...)\n_toAbstractUnitRanges(::Tuple{}) = ()\n\n# ensure that the indices are consistent in the constructor\n_checkindices(A::AbstractArray, indices, label) = _checkindices(ndims(A), indices, label)\nfunction _checkindices(N::Integer, indices, label)\n    throw_argumenterror(N, indices, label) = throw(ArgumentError(label*\" $indices are not compatible with a $(N)D array\"))\n    N == length(indices) || throw_argumenterror(N, indices, label)\nend\n\n@inline _indexedby(r::AbstractVector, ax::Tuple{Any}) = _indexedby(r, ax[1])\n@inline _indexedby(r::AbstractUnitRange{<:Integer}, ::Base.OneTo) = no_offset_view(r)\n@inline _indexedby(r::AbstractUnitRange{Bool}, ::Base.OneTo) = no_offset_view(r)\n@inline _indexedby(r::AbstractVector, ::Base.OneTo) = no_offset_view(r)\n@inline function _indexedby(r::AbstractUnitRange{<:Integer}, ax::AbstractUnitRange)\n\tof = convert(eltype(r), first(ax) - 1)\n\tIdOffsetRange(_subtractoffset(r, of), of)\nend\n@inline _indexedby(r::AbstractUnitRange{Bool}, ax::AbstractUnitRange) = OffsetArray(r, ax)\n@inline _indexedby(r::AbstractVector, ax::AbstractUnitRange) = OffsetArray(r, ax)\n\n# These functions are equivalent to the broadcasted operation r .- of\n# However these ensure that the result is an AbstractRange even if a specific\n# broadcasting behavior is not defined for a custom type\n@inline _subtractoffset(r::AbstractUnitRange, of) = UnitRange(first(r) - of, last(r) - of)\n@inline _subtractoffset(r::AbstractRange, of) = range(first(r) - of, stop = last(r) - of, step = step(r))\n\n# similar to _subtractoffset, except these evaluate r .+ of\n@inline _addoffset(r::AbstractUnitRange, of) = UnitRange(first(r) + of, last(r) + of)\n@inline _addoffset(r::AbstractRange, of) = range(first(r) + of, stop = last(r) + of, step = step(r))\n\nif VERSION <= v\"1.7.0-DEV.1039\"\n    _contiguousindexingtype(r::AbstractUnitRange{<:Integer}) = UnitRange{Int}(r)\nelse\n    _contiguousindexingtype(r::AbstractUnitRange{<:Integer}) = r\nend\n\n_of_eltype(::Type{T}, M::AbstractArray{T}) where {T} = M\n_of_eltype(T, M::AbstractArray) = map(T, M)\n\n# filter the arguments to reshape to check if there are any ranges\n# If not, we may pop the parent array\n_filterreshapeinds(t::Tuple{AbstractUnitRange, Vararg{Any}}) = t\n_filterreshapeinds(t::Tuple) = _filterreshapeinds(tail(t))\n_filterreshapeinds(t::Tuple{}) = t\n_popreshape(A::AbstractArray, ax::Tuple{Vararg{Base.OneTo}}, inds::Tuple{}) = no_offset_view(A)\n_popreshape(A::AbstractArray, ax, inds) = A\n"
  },
  {
    "path": "test/customranges.jl",
    "content": "# Useful for testing indexing\nstruct ZeroBasedRange{T,A<:AbstractRange{T}} <: AbstractRange{T}\n    a :: A\n    function ZeroBasedRange(a::AbstractRange{T}) where {T}\n        @assert !Base.has_offset_axes(a)\n        new{T, typeof(a)}(a)\n    end\nend\n\nstruct ZeroBasedUnitRange{T,A<:AbstractUnitRange{T}} <: AbstractUnitRange{T}\n    a :: A\n    function ZeroBasedUnitRange(a::AbstractUnitRange{T}) where {T}\n        @assert !Base.has_offset_axes(a)\n        new{T, typeof(a)}(a)\n    end\nend\n\nfor Z in [:ZeroBasedRange, :ZeroBasedUnitRange]\n    @eval Base.parent(A::$Z) = A.a\n    @eval Base.first(A::$Z) = first(A.a)\n    @eval Base.length(A::$Z) = length(A.a)\n    @eval Base.last(A::$Z) = last(A.a)\n    @eval Base.size(A::$Z) = size(A.a)\n    @eval Base.axes(A::$Z) = map(x -> IdentityUnitRange(0:x-1), size(A.a))\n    @eval Base.getindex(A::$Z, i::Int) = A.a[i + 1]\n    @eval Base.getindex(A::$Z, i::Integer) = A.a[i + 1]\n    @eval Base.firstindex(A::$Z) = 0\n    @eval Base.step(A::$Z) = step(A.a)\n    @eval OffsetArrays.no_offset_view(A::$Z) = A.a\n    @eval function Base.show(io::IO, A::$Z)\n        show(io, A.a)\n        print(io, \" with indices $(axes(A,1))\")\n    end\nend\n\nfor Z in [:ZeroBasedRange, :ZeroBasedUnitRange]\n    for R in [:AbstractRange, :AbstractUnitRange, :StepRange]\n        @eval @inline function Base.getindex(A::$Z, r::$R{<:Integer})\n            @boundscheck checkbounds(A, r)\n            OffsetArrays._indexedby(A.a[r .+ 1], axes(r))\n        end\n    end\n\n    for R in [:ZeroBasedUnitRange, :ZeroBasedRange]\n        @eval @inline function Base.getindex(A::$Z, r::$R{<:Integer})\n            @boundscheck checkbounds(A, r)\n            OffsetArrays._indexedby(A.a[r.a .+ 1], axes(r))\n        end\n    end\n\n    for R in [:IIUR, :IdOffsetRange]\n        @eval @inline function Base.getindex(A::$Z, r::$R)\n            @boundscheck checkbounds(A, r)\n            OffsetArrays._indexedby(A.a[r .+ 1], axes(r))\n        end\n    end\n\n    for R in [:AbstractUnitRange, :IdOffsetRange, :IdentityUnitRange, :SliceIntUR, :StepRange, :StepRangeLen, :LinRange]\n        @eval @inline function Base.getindex(A::$R, r::$Z)\n            @boundscheck checkbounds(A, r)\n            OffsetArrays._indexedby(A[r.a], axes(r))\n        end\n    end\n    @eval @inline function Base.getindex(A::StepRangeLen{<:Any,<:Base.TwicePrecision,<:Base.TwicePrecision}, r::$Z)\n        @boundscheck checkbounds(A, r)\n        OffsetArrays._indexedby(A[r.a], axes(r))\n    end\n\n    @eval Base.reshape(z::$Z, inds::Tuple{}) = reshape(parent(z), inds)\n    @eval Base.reshape(z::$Z, inds::Tuple{Int, Vararg{Int}}) = reshape(parent(z), inds)\n    @eval Base.reshape(z::$Z, inds::Tuple{Union{Int, AbstractUnitRange{<:Integer}}, Vararg{Union{Int, AbstractUnitRange{<:Integer}}}}) = reshape(parent(z), inds)\nend\n\n# A basic range that does not have specialized vector indexing methods defined\n# In this case the best that we may do is to return an OffsetArray\n# Despite this, an indexing operation involving this type should preserve the axes of the indices\nstruct CustomRange{T,A<:AbstractRange{T}} <: AbstractRange{T}\n    a :: A\nend\nBase.parent(r::CustomRange) = r.a\nBase.size(r::CustomRange) = size(parent(r))\nBase.length(r::CustomRange) = length(parent(r))\nBase.axes(r::CustomRange) = axes(parent(r))\nBase.first(r::CustomRange) = first(parent(r))\nBase.last(r::CustomRange) = last(parent(r))\nBase.step(r::CustomRange) = step(parent(r))\nBase.getindex(r::CustomRange, i::Int) = getindex(parent(r), i)\n"
  },
  {
    "path": "test/origin.jl",
    "content": "using OffsetArrays: Origin\n@testset \"Origin\" begin\n    get_origin(A::AbstractArray) = first.(axes(A))\n\n    @test Origin(0) != Origin((0, ))\n    @test Origin(CartesianIndex(1, 2)) === Origin((1, 2)) === Origin(1, 2)\n\n    @test Origin(Int32.((1,2))) == Origin(Int64.((1,2)))\n    @test Origin(Int32.((1,2))...) == Origin(Int64.((1,2))...) == Origin((1.0, 2.0))\n    @test Origin(Int32(1)) == Origin(Int64(1)) == Origin(1.0)\n    @test_throws Exception Origin(1.5)\n\n    # 0d\n    A = OffsetArray(zeros())\n    B = OffsetArray(zeros(), Origin())\n    @test axes(A) == axes(B)\n\n    # 1d\n    v = [1, 2]\n    @test get_origin(OffsetArray(v, Origin(2))) == (2, )\n    ov = OffsetArray(v, -3)\n    @test get_origin(OffsetArray(ov, Origin(2))) == (2, )\n    @test get_origin(OffsetVector(ov, Origin(2))) == (2, )\n    @test get_origin(OffsetArray(ov, Origin((2, )))) == (2, )\n\n    # 2d\n    a = [1 2;3 4]\n    @test get_origin(OffsetArray(a, Origin(0))) == (0, 0)\n    oa = OffsetArray(a, -3, -3)\n    @test get_origin(OffsetArray(oa, Origin(0))) == (0, 0)\n    @test get_origin(OffsetMatrix(oa, Origin(0))) == (0, 0)\n    @test get_origin(OffsetArray(oa, Origin(1, 2))) == (1, 2)\n\n    # 3d\n    a = ones(3, 3, 3)\n    @test get_origin(OffsetArray(a, Origin(0))) == (0, 0, 0)\n    oa = OffsetArray(a, -3, -3, -3)\n    @test get_origin(OffsetArray(oa, Origin(0))) == (0, 0, 0)\n    @test get_origin(OffsetArray(oa, Origin(1, 2, 3))) == (1, 2, 3)\n\n    # Scalar broadcasting\n    let\n        a = [ [1,2,3], [4,5,6] ]\n        oa = OffsetVector.(a, Origin(0))\n        @test get_origin.(oa) == [ (0,), (0,) ]\n\n        a = [ [1 2; 3 4], [5 6 7; 8 9 10] ]\n        oa = OffsetArray.(a, Origin(0, -1))\n        @test get_origin.(oa) == [ (0,-1), (0,-1) ]\n    end\n\n    @testset \"as a callable\" begin\n        a = [1 2; 3 4];\n        @test OffsetArray(a, Origin(2)) == Origin(2)(a)\n        for (index, firstinds) in Any[(1, (1,1)), ((2,3), (2,3))]\n            b = Origin(index)(a)\n            @test first.(axes(b)) == firstinds\n            @test Origin(b) == Origin(firstinds)\n            @test Origin(OffsetArrays.no_offset_view(b)) == Origin(ntuple(_ -> 1, Val(ndims(b))))\n        end\n        # compatibility with other array types\n        @test Origin(Ones(2,2)) == Origin(1,1)\n        @test Origin(SMatrix{2,2,Int,4}(1,2,3,4)) == Origin(1,1)\n    end\n    @testset \"display\" begin\n        io = IOBuffer()\n        show(io, Origin(1))\n        @test String(take!(io)) == \"Origin(1)\"\n        show(io, Origin(1, 1))\n        @test String(take!(io)) == \"Origin(1, 1)\"\n    end\n\n    @testset \"avoid overflow (issue #279)\" begin\n        A = Origin(typemin(Int)+1)(rand(3,3))\n        B = Origin(typemax(Int)-4)(A)\n        @test first.(axes(B)) == ntuple(_ -> typemax(Int)-4, Val(ndims(B)))\n    end\nend\n"
  },
  {
    "path": "test/runtests.jl",
    "content": "using Adapt\nusing Aqua\nusing Base: Slice\nusing CatIndices: BidirectionalVector\nusing DelimitedFiles\nusing DistributedArrays\nusing Documenter\nusing EllipsisNotation\nusing FillArrays\nusing LinearAlgebra\nusing OffsetArrays\nusing OffsetArrays: IdentityUnitRange, no_offset_view, IIUR, Origin, IdOffsetRange\nusing StaticArrays\nusing Test\n\nconst SliceIntUR = Slice{<:AbstractUnitRange{<:Integer}}\n\nDocMeta.setdocmeta!(OffsetArrays, :DocTestSetup, :(using OffsetArrays); recursive=true)\n\nno_offset_axes(x, d) = no_offset_view(axes(x, d))\nno_offset_axes(x) = map(no_offset_view, axes(x))\n\n# https://github.com/JuliaLang/julia/pull/29440\nif VERSION < v\"1.1.0-DEV.389\"\n    Base.:(:)(I::CartesianIndex{N}, J::CartesianIndex{N}) where N =\n        CartesianIndices(map((i,j) -> i:j, Tuple(I), Tuple(J)))\nend\n\n# Custom index types\nstruct ZeroBasedIndexing end\nstruct NewColon end\nstruct TupleOfRanges{N}\n    x ::NTuple{N, UnitRange{Int}}\nend\n\ninclude(\"customranges.jl\")\n\nfunction same_value(r1, r2)\n    length(r1) == length(r2) || return false\n    for (v1, v2) in zip(r1, r2)\n        v1 == v2 || return false\n    end\n    return true\nend\n\n@testset \"Project meta quality checks\" begin\n    Aqua.test_all(OffsetArrays, piracies=false)\n    if VERSION >= v\"1.2\"\n        doctest(OffsetArrays, manual = false)\n    end\nend\n\n@testset \"IdOffsetRange\" begin\n\n    function check_indexed_by(r, rindx)\n        for i in rindx\n            r[i]\n        end\n        @test_throws BoundsError r[minimum(rindx)-1]\n        @test_throws BoundsError r[maximum(rindx)+1]\n        return nothing\n    end\n\n    ro = OffsetArrays.IdOffsetRange(Base.OneTo(3))\n    rs = OffsetArrays.IdOffsetRange(3:5, -2)\n    @test typeof(ro) !== typeof(rs)\n    @test same_value(ro, 1:3)\n    check_indexed_by(ro, 1:3)\n    @test same_value(rs, 1:3)\n    check_indexed_by(rs, -1:1)\n    @test firstindex(ro) == 1\n    @test lastindex(ro) == 3\n    @test firstindex(rs) == -1\n    @test lastindex(rs) == 1\n    @test @inferred(typeof(ro)(ro)) === ro\n    @test @inferred(OffsetArrays.IdOffsetRange{Int}(ro))   === ro\n    @test @inferred(OffsetArrays.IdOffsetRange{Int16}(ro)) === OffsetArrays.IdOffsetRange(Base.OneTo(Int16(3)))\n    @test @inferred(OffsetArrays.IdOffsetRange(ro))        === ro\n    @test parent(ro) === ro.parent\n    @test parent(rs) === rs.parent\n    # construction/coercion preserves the values, altering the axes if needed\n    r2 = @inferred(typeof(rs)(ro))\n    @test typeof(r2) === typeof(rs)\n    @test same_value(ro, 1:3)\n    check_indexed_by(ro, 1:3)\n    r2 = @inferred(typeof(ro)(rs))\n    @test typeof(r2) === typeof(ro)\n    @test same_value(r2, 1:3)\n    check_indexed_by(r2, 1:3)\n    # check the example in the comments\n    r = OffsetArrays.IdOffsetRange{Int,UnitRange{Int}}(3:4)\n    @test same_value(r, 3:4)\n    check_indexed_by(r, 1:2)\n    r = OffsetArrays.IdOffsetRange{Int,Base.OneTo{Int}}(3:4)\n    @test same_value(r, 3:4)\n    check_indexed_by(r, 3:4)\n    r = OffsetArrays.IdOffsetRange{Int,Base.OneTo{Int}}(3:4, -2)\n    @test same_value(r, 1:2)\n    check_indexed_by(r, 1:2)\n\n    r = OffsetArrays.IdOffsetRange{Int32, Base.OneTo{Int32}}(Base.OneTo(Int64(2)), 3)\n    @test same_value(r, 4:5)\n    check_indexed_by(r, 4:5)\n\n    r = IdOffsetRange{Int, UnitRange{Int}}(IdOffsetRange(3:5, 2), 2)\n    @test typeof(r) == IdOffsetRange{Int, UnitRange{Int}}\n    @test same_value(r, 7:9)\n    check_indexed_by(r, 5:7)\n\n    r = IdOffsetRange{Int, Base.OneTo{Int}}(IdOffsetRange(Base.OneTo(3), 1), 1)\n    @test typeof(r) == IdOffsetRange{Int,Base.OneTo{Int}}\n    @test same_value(r, 3:5)\n    check_indexed_by(r, 3:5)\n\n    rp = Base.OneTo(3)\n    r = IdOffsetRange(rp)\n    r2 = IdOffsetRange{Int,typeof(r)}(r, 1)\n    @test same_value(r2, 2:4)\n    check_indexed_by(r2, 2:4)\n\n    r2 = IdOffsetRange{Int32,IdOffsetRange{Int32,Base.OneTo{Int32}}}(r, 1)\n    @test typeof(r2) == IdOffsetRange{Int32,IdOffsetRange{Int32,Base.OneTo{Int32}}}\n    @test same_value(r2, 2:4)\n    check_indexed_by(r2, 2:4)\n\n    # eltype coercion through the AbstractUnitRange constructor\n    ro = OffsetArrays.IdOffsetRange(Base.OneTo(3))\n    @test @inferred(AbstractUnitRange{Int}(ro)) === ro\n    rb = IdOffsetRange(Base.OneTo(big(3)))\n    @test @inferred(AbstractUnitRange{Int}(rb)) === IdOffsetRange(Base.OneTo(3))\n\n    # Constructor that's round-trippable with `show`\n    rrt = IdOffsetRange(values=7:9, indices=-1:1)\n    @test same_value(rrt, 7:9)\n    check_indexed_by(rrt, -1:1)\n    @test_throws ArgumentError IdOffsetRange(values=7:9, indices=-1:2)\n    @test_throws ArgumentError IdOffsetRange(values=7:9, indices=-1:0)\n    @test_throws TypeError IdOffsetRange(values=7:9, indices=-1)\n    @test_throws UndefKeywordError IdOffsetRange(values=7:9)\n    @test_throws UndefKeywordError IdOffsetRange(indices=-1:1)\n    @test_throws MethodError IdOffsetRange(7:9, indices=-1:1)\n    @test_throws MethodError IdOffsetRange(-1:1, values=7:9)\n\n    p = IdOffsetRange(1:3, 2)\n    q = IdOffsetRange(values = p .- 2, indices = p)\n    @test same_value(q, 1:3)\n    check_indexed_by(q, p)\n\n    @testset for indices in Any[Base.OneTo(3), IdentityUnitRange(Base.OneTo(3))]\n        p = IdOffsetRange(values = IdOffsetRange(1:3, 2), indices = indices)\n        @test same_value(p, 3:5)\n        check_indexed_by(p, 1:3)\n        q = IdOffsetRange(values = Base.OneTo(3), indices = indices)\n        @test same_value(q, 1:3)\n        @test q isa IdOffsetRange{Int, Base.OneTo{Int}}\n    end\n\n    # conversion preserves both the values and the axes, throwing an error if this is not possible\n    @test @inferred(oftype(ro, ro)) === ro\n    @test @inferred(convert(OffsetArrays.IdOffsetRange{Int}, ro)) === ro\n    @test @inferred(convert(OffsetArrays.IdOffsetRange{Int}, rs)) === rs\n    @test @inferred(convert(OffsetArrays.IdOffsetRange{Int16}, ro)) === OffsetArrays.IdOffsetRange(Base.OneTo(Int16(3)))\n    r2 = @inferred(oftype(rs, ro))\n    @test typeof(r2) === typeof(rs)\n    @test same_value(r2, 1:3)\n    check_indexed_by(r2, 1:3)\n    # These two broken tests can be fixed by uncommenting the `convert` definitions\n    # in axes.jl, but unfortunately Julia may not quite be ready for this. (E.g. `reinterpretarray.jl`)\n    @test_broken try oftype(ro, rs); false catch err true end  # replace with line below\n    # @test_throws ArgumentError oftype(ro, rs)\n    @test @inferred(oftype(ro, Base.OneTo(2))) === OffsetArrays.IdOffsetRange(Base.OneTo(2))\n    @test @inferred(oftype(ro, 1:2)) === OffsetArrays.IdOffsetRange(Base.OneTo(2))\n    @test_broken try oftype(ro, 3:4); false catch err true end\n    # @test_throws ArgumentError oftype(ro, 3:4)\n\n    # broadcasting behavior with scalars (issue #104)\n    r3 = (1 .+ OffsetArrays.IdOffsetRange(3:5, -1) .+ 1) .- 1\n    @test r3 isa OffsetArrays.IdOffsetRange\n    @test same_value(r3, 3:5)\n    check_indexed_by(r3, axes(r3,1))\n\n    r = OffsetArrays.IdOffsetRange(3:5, -1)\n    rc = copyto!(similar(r), r)\n    n = big(typemax(Int))\n    @test @inferred(broadcast(+, r, n)) == @inferred(broadcast(+, n, r)) == rc .+ n\n    @test @inferred(broadcast(-, r, n)) == rc .- n\n    @test @inferred(broadcast(big, r)) == big.(rc)\n    for n in Any[2, big(typemax(Int))]\n        @test @inferred(broadcast(+, r, n)) == @inferred(broadcast(+, n, r)) == rc .+ n\n    end\n\n    @testset \"Idempotent indexing\" begin\n        @testset \"Indexing into an IdOffsetRange\" begin\n            r = OffsetArrays.IdOffsetRange(3:5, -1)\n            # Indexing with IdentityUnitRange\n            s = IdentityUnitRange(0:2)\n            @test axes(r[s]) == axes(s)\n            for i in eachindex(s)\n                @test r[s[i]] == r[s][i]\n            end\n\n            # Indexing with IdOffsetRange\n            s = OffsetArrays.IdOffsetRange(-4:-2, 4)\n            @test axes(r[s]) == axes(s)\n            for i in eachindex(s)\n                @test r[s[i]] == r[s][i]\n            end\n\n            # Indexing with UnitRange\n            s = 0:2\n            @test axes(r[s]) == axes(s)\n            for i in eachindex(s)\n                @test r[s[i]] == r[s][i]\n            end\n        end\n        @testset \"Indexing using an IdOffsetRange\" begin\n            r = OffsetArrays.IdOffsetRange(3:5, -1)\n            # Indexing into an IdentityUnitRange\n            s = IdentityUnitRange(-1:5)\n            @test axes(s[r]) == axes(r)\n            for i in eachindex(r)\n                @test s[r[i]] == s[r][i]\n            end\n\n            # Indexing into an UnitRange\n            s = -3:6\n            @test axes(s[r]) == axes(r)\n            for i in eachindex(r)\n                @test s[r[i]] == s[r][i]\n            end\n        end\n    end\n\n    # Test reduced index\n    rred = Base.reduced_index(r)\n    @test typeof(rred) == typeof(r)\n    @test length(rred) == 1\n    @test first(rred) == first(r)\n\n    @testset \"reduced_indices\" begin\n        a = reshape(1:24, 2, 3, 4)\n        sa = OffsetArray(a, (2, 3, 4));\n        @testset for dim in 1:ndims(sa)\n            sasum = sum(sa, dims = dim)\n            @test parent(sasum) == sum(a, dims = dim)\n            find = firstindex(sa, dim)\n            @test no_offset_axes(sasum, dim) == find:find\n        end\n    end\n\n    @testset \"conversion to AbstractUnitRange\" begin\n        r = IdOffsetRange(1:2)\n        @test AbstractUnitRange{Int}(r) === r\n        r2 = IdOffsetRange(big(1):big(2))\n        @test AbstractUnitRange{Int}(r2) === r\n        @test AbstractUnitRange{BigInt}(r2) === r2\n\n        if v\"1.5\" < VERSION\n            @test OrdinalRange{Int,Int}(r2) === r\n            @test OrdinalRange{BigInt,BigInt}(r2) === r2\n        end\n    end\n\n    @testset \"Bool IdOffsetRange (issue #223)\" begin\n        for b1 in [false, true], b2 in [false, true]\n            r = IdOffsetRange(b1:b2)\n            @test first(r) === b1\n            @test last(r) === b2\n        end\n        @test_throws ArgumentError IdOffsetRange(true:true, true)\n        @test_throws ArgumentError IdOffsetRange{Bool,UnitRange{Bool}}(true:true, true)\n        @test_throws ArgumentError IdOffsetRange{Bool,IdOffsetRange{Bool,UnitRange{Bool}}}(IdOffsetRange(true:true), true)\n    end\n\n    @testset \"Logical indexing\" begin\n        @testset \"indexing with a single bool\" begin\n            r = IdOffsetRange(1:2)\n            @test_throws ArgumentError r[true]\n            @test_throws ArgumentError r[false]\n        end\n        @testset \"indexing with a Bool UnitRange\" begin\n            r = IdOffsetRange(1:0)\n\n            @test r[true:false] == 1:0\n            @test r[true:false] == collect(r)[true:false]\n            @test_throws BoundsError r[true:true]\n            @test_throws BoundsError r[false:false]\n            @test_throws BoundsError r[false:true]\n\n            r = IdOffsetRange(1:1)\n\n            @test r[true:true] == 1:1\n            @test r[true:true] == collect(r)[true:true]\n\n            @test r[false:false] == 1:0\n            @test r[false:false] == collect(r)[false:false]\n\n            @test_throws BoundsError r[true:false]\n            @test_throws BoundsError r[false:true]\n\n            r = IdOffsetRange(1:2)\n\n            @test r[false:true] == 2:2\n            @test r[false:true] == collect(r)[false:true]\n\n            @test_throws BoundsError r[true:true]\n            @test_throws BoundsError r[true:false]\n            @test_throws BoundsError r[false:false]\n        end\n        @testset \"indexing with a Bool IdOffsetRange\" begin\n            # bounds-checking requires the axes of the indices to match that of the array\n            function testlogicalindexing(r, r2)\n                r3 = r[r2];\n                @test no_offset_view(r3) == collect(r)[collect(r2)]\n            end\n\n            r = IdOffsetRange(10:9)\n            r2 = IdOffsetRange(true:false)\n            testlogicalindexing(r, r2)\n\n            r = IdOffsetRange(10:10)\n            r2 = IdOffsetRange(false:false)\n            testlogicalindexing(r, r2)\n            r2 = IdOffsetRange(true:true)\n            testlogicalindexing(r, r2)\n\n            r = IdOffsetRange(10:10, 1)\n            r2 = IdOffsetRange(false:false, 1) # effectively true:true with indices 2:2\n            testlogicalindexing(r, r2)\n\n            r = IdOffsetRange(10:11)\n            r2 = IdOffsetRange(false:true)\n            testlogicalindexing(r, r2)\n        end\n        @testset \"indexing with a Bool StepRange\" begin\n            r = IdOffsetRange(1:0)\n\n            @test r[true:true:false] == 1:1:0\n            @test_throws BoundsError r[true:true:true]\n            @test_throws BoundsError r[false:true:false]\n            @test_throws BoundsError r[false:true:true]\n\n            r = IdOffsetRange(1:1)\n\n            @test r[true:true:true] == 1:1:1\n            @test r[true:true:true] == collect(r)[true:true:true]\n            @test axes(r[true:true:true], 1) == 1:1\n\n            @test r[false:true:false] == 1:1:0\n            @test r[false:true:false] == collect(r)[false:true:false]\n\n            # StepRange{Bool,Int}\n            s = StepRange(true, 1, true)\n            @test r[s] == 1:1:1\n            @test r[s] == collect(r)[s]\n\n            s = StepRange(true, 2, true)\n            @test r[s] == 1:1:1\n            @test r[s] == collect(r)[s]\n\n            s = StepRange(false, 1, false)\n            @test r[s] == 1:1:0\n            @test r[s] == collect(r)[s]\n\n            s = StepRange(false, 2, false)\n            @test r[s] == 1:1:0\n            @test r[s] == collect(r)[s]\n\n            @test_throws BoundsError r[true:true:false]\n            @test_throws BoundsError r[false:true:true]\n\n            r = IdOffsetRange(1:2)\n\n            @test r[false:true:true] == 2:1:2\n            @test r[false:true:true] == collect(r)[false:true:true]\n\n            # StepRange{Bool,Int}\n            s = StepRange(false, 1, true)\n            @test r[s] == 2:1:2\n            @test r[s] == collect(r)[s]\n\n            @test_throws BoundsError r[true:true:true]\n            @test_throws BoundsError r[true:true:false]\n            @test_throws BoundsError r[false:true:false]\n        end\n    end\n\n    @testset \"iteration\" begin\n        # parent has Base.OneTo axes\n        A = ones(4:10)\n        ax = axes(A, 1)\n        ind, st = iterate(ax)\n        @test A[ind] == A[4]\n        ind, st = iterate(ax, st)\n        @test A[ind] == A[5]\n\n        # parent doesn't have Base.OneTo axes\n        B = @view A[:]\n        C = OffsetArray(B, 0)\n        ax = axes(C, 1)\n        ind, st = iterate(ax)\n        @test C[ind] == C[4]\n        ind, st = iterate(ax, st)\n        @test C[ind] == C[5]\n    end\nend\n\n# used in testing the constructor\nstruct WeirdInteger{T} <: Integer\n    x :: T\nend\n# assume that it doesn't behave as expected\nBase.Int(a::WeirdInteger) = a\n\n@testset \"Constructors\" begin\n    @testset \"Single-entry arrays in dims 0:5\" begin\n        for n = 0:5\n            for z in (OffsetArray(ones(Int,ntuple(d->1,n)), ntuple(x->x-1,n)),\n                    fill!(OffsetArray{Float64}(undef, ntuple(x->x:x, n)), 1),\n                    fill!(OffsetArray{Float64}(undef, ntuple(x->x:x, n)...), 1),\n                    fill!(OffsetArray{Float64,n}(undef, ntuple(x->x:x, n)), 1),\n                    fill!(OffsetArray{Float64,n}(undef, ntuple(x->x:x, n)...), 1))\n                @test length(LinearIndices(z)) == 1\n                @test no_offset_axes(z) == ntuple(x->x:x, n)\n                @test z[1] == 1\n            end\n        end\n        a0 = reshape([3])\n        a = OffsetArray(a0)\n        @test axes(a) == ()\n        @test ndims(a) == 0\n        @test a[] == 3\n        @test a === OffsetArray(a, ())\n        @test_throws ArgumentError OffsetArray(a, 0)\n        @test_throws ArgumentError OffsetArray(a0, 0)\n    end\n\n    @testset \"OffsetVector\" begin\n        # initialization\n        one_based_axes = Any[\n            (Base.OneTo(4), ),\n            (1:4, ),\n            (big(1):big(4), ),\n            (CartesianIndex(1):CartesianIndex(4), ),\n            (IdentityUnitRange(1:4), ),\n            (IdOffsetRange(1:4),),\n            (IdOffsetRange(3:6, -2),)\n        ]\n\n        offset_axes = Any[\n            (-1:2, ),\n            (big(-1):big(2), ),\n            (CartesianIndex(-1):CartesianIndex(2), ),\n            (IdentityUnitRange(-1:2), ),\n            (IdOffsetRange(-1:2),),\n            (IdOffsetRange(3:6, -4),)\n        ]\n\n        offsets = size.(one_based_axes[1], 1)\n        offsets_big = map(big, offsets)\n\n        for inds in Any[offsets, offsets_big, one_based_axes...]\n            # test indices API\n            a = OffsetVector{Float64}(undef, inds)\n            @test eltype(a) === Float64\n            @test axes(a) === axes(OffsetVector{Float64}(undef, inds...)) === axes(OffsetArray{Float64, 1}(undef, inds)) === axes(OffsetArray{Float64}(undef, inds))\n            @test axes(a) === (IdOffsetRange(Base.OneTo(4), 0), )\n            @test a.offsets === (0, )\n            @test axes(a.parent) == (Base.OneTo(4), )\n\n            a = OffsetVector{Nothing}(nothing, inds)\n            @test eltype(a) === Nothing\n            @test axes(a) === axes(OffsetVector{Nothing}(nothing, inds...)) === axes(OffsetArray{Nothing, 1}(nothing, inds))\n            @test axes(a) === (IdOffsetRange(Base.OneTo(4), 0), )\n\n            a = OffsetVector{Missing}(missing, inds)\n            @test eltype(a) === Missing\n            @test axes(a) === axes(OffsetVector{Missing}(missing, inds...)) === axes(OffsetArray{Missing, 1}(missing, inds))\n            @test axes(a) === (IdOffsetRange(Base.OneTo(4), 0), )\n        end\n\n        # nested OffsetVectors\n        for inds in Any[offsets, offsets_big]\n            a = OffsetVector{Float64}(undef, inds)\n            b = OffsetVector(a, inds); b2 = OffsetVector(a, inds...);\n            @test eltype(b) === eltype(b2) === Float64\n            @test axes(b, 1) === axes(b2, 1) === IdOffsetRange(Base.OneTo(4), 4)\n        end\n\n        # offset indexing\n        for inds in offset_axes\n            # test offsets\n            a = OffsetVector{Float64}(undef, inds)\n            ax = (IdOffsetRange(Base.OneTo(4), -2), )\n            @test a.offsets === (-2, )\n            @test axes(a.parent) == (Base.OneTo(4), )\n            @test axes(a) === ax\n            a = OffsetVector{Nothing}(nothing, inds)\n            @test axes(a) === ax\n            a = OffsetVector{Missing}(missing, inds)\n            @test axes(a) === ax\n\n            for (T, t) in Any[(Nothing, nothing), (Missing, missing)]\n                a = OffsetVector{Union{T, Vector{Int}}}(undef, inds)\n                @test !isassigned(a, -1)\n                @test eltype(a) === Union{T, Vector{Int}}\n                @test axes(a) === ax\n\n                a = OffsetVector{Union{T, Vector{Int}}}(t, inds)\n                @test a[-1] === t\n            end\n        end\n        @test_throws Union{ArgumentError, ErrorException} OffsetVector{Float64}(undef, -2) # only positive number works\n\n        # convenient constructors\n        a = rand(4)\n        for inds in offset_axes\n            oa1 = OffsetVector(a, inds...)\n            oa2 = OffsetVector(a, inds)\n            oa3 = OffsetArray(a, inds...)\n            oa4 = OffsetArray(a, inds)\n            @test oa1 === oa2 === oa3 === oa4\n            @test axes(oa1) === (IdOffsetRange(Base.OneTo(4), -2), )\n            @test parent(oa1) === a\n            @test oa1.offsets === (-2, )\n        end\n\n        oa = OffsetArray(a, :)\n        @test oa === OffsetArray(a, (:, )) === OffsetArray(a, axes(a)) === OffsetVector(a, :) === OffsetVector(a, axes(a))\n        @test oa == a\n        @test axes(oa) == axes(a)\n        @test axes(oa) !== axes(a)\n\n        # nested offset array\n        a = rand(4)\n        oa = OffsetArray(a, -1)\n        for inds in Any[.-oa.offsets, one_based_axes...]\n            ooa = OffsetArray(oa, inds)\n            @test typeof(parent(ooa)) <: Vector\n            @test ooa === OffsetArray(oa, inds...) === OffsetVector(oa, inds) === OffsetVector(oa, inds...)\n            @test ooa == a\n            @test axes(ooa) == axes(a)\n            @test axes(ooa) !== axes(a)\n        end\n\n        # overflow bounds check\n        v = rand(5)\n        @test axes(OffsetVector(v, typemax(Int)-length(v))) == (IdOffsetRange(axes(v)[1], typemax(Int)-length(v)), )\n        @test_throws OverflowError OffsetVector(v, typemax(Int)-length(v)+1)\n        ao = OffsetArray(v, typemin(Int))\n        ao2 = OffsetArray{Float64, 1, typeof(ao)}(ao, (-1, ))\n        @test no_offset_axes(ao2, 1) == typemin(Int) .+ (0:length(v)-1)\n        ao2 = OffsetArray(ao, (-1,))\n        @test no_offset_axes(ao2, 1) == typemin(Int) .+ (0:length(v)-1)\n        @test_throws OverflowError OffsetArray{Float64, 1, typeof(ao)}(ao, (-2, )) # inner Constructor\n        @test_throws OverflowError OffsetArray(ao, (-2, )) # convenient constructor accumulate offsets\n        @test_throws OverflowError OffsetVector(1:0, typemax(Int))\n        @test_throws OverflowError OffsetVector(OffsetVector(1:0, 0), typemax(Int))\n        @test_throws OverflowError OffsetArray(zeros(Int, typemax(Int):typemax(Int)), 2)\n        @test_throws OverflowError OffsetArray(v, OffsetArrays.Origin(typemax(Int)))\n\n        b = OffsetArray(OffsetArray(big(1):2, 1), typemax(Int)-1)\n        @test no_offset_axes(b, 1) == big(typemax(Int)) .+ (1:2)\n\n        @testset \"OffsetRange\" begin\n            for r in Any[1:100, big(1):big(2)]\n                a = OffsetVector(r, 4)\n                @test first(r) in a\n                @test !(last(r) + 1 in a)\n            end\n\n            @testset \"BigInt axes\" begin\n                r = OffsetArray(1:big(2)^65, 4000)\n                @test eltype(r) === BigInt\n                @test no_offset_axes(r, 1) == (big(1):big(2)^65) .+ 4000\n            end\n        end\n\n        # disallow OffsetVector(::Array{<:Any, N}, offsets) where N != 1\n        @test_throws ArgumentError OffsetVector(zeros(2,2), (2, 2))\n        @test_throws ArgumentError OffsetVector(zeros(2,2), 2, 2)\n        @test_throws ArgumentError OffsetVector(zeros(2,2), (1:2, 1:2))\n        @test_throws ArgumentError OffsetVector(zeros(2,2), 1:2, 1:2)\n        @test_throws ArgumentError OffsetVector(zeros(), ())\n        @test_throws ArgumentError OffsetVector(zeros())\n        @test_throws ArgumentError OffsetVector(zeros(2,2), ())\n        @test_throws ArgumentError OffsetVector(zeros(2,2))\n        @test_throws ArgumentError OffsetVector(zeros(2,2), 2)\n        @test_throws ArgumentError OffsetVector(zeros(2,2), (2,))\n        @test_throws ArgumentError OffsetVector(zeros(2:3,2:3), 2, 3)\n        @test_throws ArgumentError OffsetVector(zeros(2:3,2:3), (2, 4))\n        @test_throws ArgumentError OffsetVector(zeros(2:3,2:3), ())\n        @test_throws ArgumentError OffsetVector(zeros(2:3,2:3))\n\n        # eltype of an OffsetArray should match that of the parent (issue #162)\n        @test_throws TypeError OffsetVector{Float64,Vector{ComplexF64}}\n        # ndim of an OffsetArray should match that of the parent\n        @test_throws TypeError OffsetVector{Float64,Matrix{Float64}}\n    end\n\n    @testset \"OffsetMatrix\" begin\n        # initialization\n\n        one_based_axes = Any[\n                (Base.OneTo(4), Base.OneTo(3)),\n                (1:4, 1:3),\n                (big(1):big(4), big(1):big(3)),\n                (CartesianIndex(1, 1):CartesianIndex(4, 3), ),\n                (CartesianIndex(1):CartesianIndex(4), CartesianIndex(1):CartesianIndex(3)),\n                (CartesianIndex(1):CartesianIndex(4), 1:3),\n                (IdentityUnitRange(1:4), IdentityUnitRange(1:3)),\n                (IdOffsetRange(1:4), IdOffsetRange(1:3)),\n                (IdOffsetRange(3:6, -2), IdOffsetRange(3:5, -2)),\n                (IdOffsetRange(3:6, -2), IdentityUnitRange(1:3)),\n                (IdOffsetRange(3:6, -2), 1:3),\n        ]\n\n        offset_axes = Any[\n                (-1:2, 0:2),\n                (big(-1):big(2), big(0):big(2)),\n                (CartesianIndex(-1, 0):CartesianIndex(2, 2), ),\n                (-1:2, CartesianIndex(0):CartesianIndex(2)),\n                (CartesianIndex(-1):CartesianIndex(2), CartesianIndex(0):CartesianIndex(2)),\n                (CartesianIndex(-1):CartesianIndex(2), 0:2),\n                (IdentityUnitRange(-1:2), 0:2),\n                (IdOffsetRange(-1:2), IdOffsetRange(0:2)),\n                (IdOffsetRange(3:6, -4), IdOffsetRange(2:4, -2)),\n                (IdOffsetRange(3:6, -4), IdentityUnitRange(0:2)),\n                (IdOffsetRange(-1:2), 0:2),\n        ]\n\n        offsets = size.(one_based_axes[1], 1)\n        offsets_big = map(big, offsets)\n\n        for inds in Any[offsets, offsets_big, one_based_axes...]\n            # test API\n            a = OffsetMatrix{Float64}(undef, inds)\n            ax = (IdOffsetRange(Base.OneTo(4), 0), IdOffsetRange(Base.OneTo(3), 0))\n            @test eltype(a) === Float64\n            @test axes(a) === axes(OffsetMatrix{Float64}(undef, inds...)) === axes(OffsetArray{Float64, 2}(undef, inds)) === axes(OffsetArray{Float64, 2}(undef, inds...)) === axes(OffsetArray{Float64}(undef, inds))\n            @test axes(a) === ax\n            @test a.offsets === (0, 0)\n            @test axes(a.parent) == (Base.OneTo(4), Base.OneTo(3))\n\n            a = OffsetMatrix{Nothing}(nothing, inds)\n            @test eltype(a) === Nothing\n            @test axes(a) === axes(OffsetMatrix{Nothing}(nothing, inds...)) === axes(OffsetArray{Nothing, 2}(nothing, inds)) === axes(OffsetArray{Nothing, 2}(nothing, inds...))\n            @test axes(a) === ax\n\n            a = OffsetMatrix{Missing}(missing, inds)\n            @test eltype(a) === Missing\n            @test axes(a) === axes(OffsetMatrix{Missing}(missing, inds...)) === axes(OffsetArray{Missing, 2}(missing, inds)) === axes(OffsetArray{Missing, 2}(missing, inds...))\n            @test axes(a) === ax\n        end\n        @test_throws Union{ArgumentError, ErrorException} OffsetMatrix{Float64}(undef, 2, -2) # only positive numbers works\n\n        # nested OffsetMatrices\n        for inds in Any[offsets, offsets_big]\n            a = OffsetMatrix{Float64}(undef, inds)\n            b = OffsetMatrix(a, inds); b2 = OffsetMatrix(a, inds...);\n            @test eltype(b) === eltype(b2) === Float64\n            @test axes(b, 1) === axes(b2, 1) === IdOffsetRange(Base.OneTo(4), 4)\n            @test axes(b, 2) === axes(b2, 2) === IdOffsetRange(Base.OneTo(3), 3)\n        end\n\n        for inds in offset_axes\n            # test offsets\n            a = OffsetMatrix{Float64}(undef, inds)\n            ax = (IdOffsetRange(Base.OneTo(4), -2), IdOffsetRange(Base.OneTo(3), -1))\n            @test a.offsets === (-2, -1)\n            @test axes(a.parent) == (Base.OneTo(4), Base.OneTo(3))\n            @test axes(a) === ax\n            a = OffsetMatrix{Nothing}(nothing, inds)\n            @test axes(a) === ax\n            a = OffsetMatrix{Missing}(missing, inds)\n            @test axes(a) === ax\n\n            for (T, t) in Any[(Nothing, nothing), (Missing, missing)]\n                a = OffsetMatrix{Union{T, Vector{Int}}}(undef, inds)\n                @test !isassigned(a, -1, 0)\n                @test eltype(a) === Union{T, Vector{Int}}\n                @test axes(a) === ax\n\n                a = OffsetMatrix{Union{T, Vector{Int}}}(t, inds)\n                @test a[-1, 0] === t\n            end\n        end\n\n        # convenient constructors\n        a = rand(4, 3)\n        for inds in offset_axes\n            ax = (IdOffsetRange(Base.OneTo(4), -2), IdOffsetRange(Base.OneTo(3), -1))\n            oa1 = OffsetMatrix(a, inds...)\n            oa2 = OffsetMatrix(a, inds)\n            oa3 = OffsetArray(a, inds...)\n            oa4 = OffsetArray(a, inds)\n            @test oa1 === oa2 === oa3 === oa4\n            @test axes(oa1) === ax\n            @test parent(oa1) === a\n            @test oa1.offsets === (-2, -1)\n        end\n        oa = OffsetArray(a, :, axes(a, 2))\n        @test oa === OffsetArray(a, (axes(oa, 1), :)) === OffsetArray(a, axes(a)) === OffsetMatrix(a, (axes(oa, 1), :)) === OffsetMatrix(a, axes(a))\n        @test oa == a\n        @test axes(oa) == axes(a)\n        @test axes(oa) !== axes(a)\n\n        oa = OffsetMatrix(a, :, 2:4)\n        @test oa === OffsetMatrix(a, axes(a, 1), 2:4) === OffsetMatrix(a, (axes(oa, 1), 2:4))\n\n        # nested offset array\n        a = rand(4, 3)\n        oa = OffsetArray(a, -1, -2)\n        for inds in Any[.-oa.offsets, one_based_axes...]\n            ooa = OffsetArray(oa, inds)\n            @test ooa === OffsetArray(oa, inds...) === OffsetMatrix(oa, inds) === OffsetMatrix(oa, inds...)\n            @test typeof(parent(ooa)) <: Matrix\n            @test ooa == a\n            @test axes(ooa) == axes(a)\n            @test axes(ooa) !== axes(a)\n        end\n\n        # overflow bounds check\n        a = rand(4, 3)\n        @test axes(OffsetMatrix(a, typemax(Int)-size(a, 1), 0)) == (IdOffsetRange(axes(a)[1], typemax(Int)-size(a, 1)), axes(a, 2))\n        @test_throws OverflowError OffsetMatrix(a, typemax(Int)-size(a,1)+1, 0)\n        @test_throws OverflowError OffsetMatrix(a, 0, typemax(Int)-size(a, 2)+1)\n\n        # disallow OffsetMatrix(::Array{<:Any, N}, offsets) where N != 2\n        @test_throws ArgumentError OffsetMatrix(zeros(2), (2,))\n        @test_throws ArgumentError OffsetMatrix(zeros(2), 2)\n        @test_throws ArgumentError OffsetMatrix(zeros(2), (1:2,))\n        @test_throws ArgumentError OffsetMatrix(zeros(2), 1:2)\n        @test_throws ArgumentError OffsetMatrix(zeros(), ())\n        @test_throws ArgumentError OffsetMatrix(zeros())\n        @test_throws ArgumentError OffsetMatrix(zeros(2), ())\n        @test_throws ArgumentError OffsetMatrix(zeros(2))\n        @test_throws ArgumentError OffsetMatrix(zeros(2), (1, 2))\n        @test_throws ArgumentError OffsetMatrix(zeros(2), 1, 2)\n        @test_throws ArgumentError OffsetMatrix(zeros(2:3), (2,))\n        @test_throws ArgumentError OffsetMatrix(zeros(2:3), 2)\n        @test_throws ArgumentError OffsetMatrix(zeros(2:3, 1:2, 1:2), (2,0,0))\n        @test_throws ArgumentError OffsetMatrix(zeros(2:3, 1:2, 1:2), 2,0,0)\n        @test_throws ArgumentError OffsetMatrix(zeros(2:3, 1:2, 1:2), ())\n        @test_throws ArgumentError OffsetMatrix(zeros(2:3, 1:2, 1:2))\n\n        # eltype of an OffsetArray should match that of the parent (issue #162)\n        @test_throws TypeError OffsetMatrix{Float64,Matrix{ComplexF64}}\n        # ndim of an OffsetArray should match that of the parent\n        @test_throws TypeError OffsetMatrix{Float64,Vector{Float64}}\n    end\n\n    # no need to duplicate the 2D case here,\n    # only add some special test cases\n    @testset \"OffsetArray\" begin\n        a = rand(2, 2, 2)\n        oa = OffsetArray(a, 0:1, 3:4, 2:3)\n        @test OffsetArray(a, CartesianIndices(axes(oa))) == oa\n        @test no_offset_axes(OffsetArray(a, :, CartesianIndices((3:4, 2:3)))) == (1:2, 3:4, 2:3)\n        @test no_offset_axes(OffsetArray(a, 10:11, CartesianIndices((3:4, 2:3)) )) == (10:11, 3:4, 2:3)\n        @test no_offset_axes(OffsetArray(a, CartesianIndices((3:4, 2:3)), :)) == (3:4, 2:3, 1:2)\n        @test no_offset_axes(OffsetArray(a, CartesianIndices((3:4, 2:3)), 10:11)) == (3:4, 2:3, 10:11)\n        @test no_offset_axes(OffsetArray(a, :, :, CartesianIndices((3:4,)) )) == (1:2, 1:2, 3:4)\n        @test no_offset_axes(OffsetArray(a, 10:11, :, CartesianIndices((3:4,)) )) == (10:11, 1:2, 3:4)\n        @test no_offset_axes(OffsetArray(a, 10:11, 2:3, CartesianIndices((3:4,)) )) == (10:11, 2:3, 3:4)\n\n        # ignore empty CartesianIndices\n        @test OffsetArray(a, CartesianIndices(()), 0:1, :, 2:3) == OffsetArray(a, 0:1, :, 2:3)\n        @test OffsetArray(a, 0:1, CartesianIndices(()), :, 2:3) == OffsetArray(a, 0:1, :, 2:3)\n        @test OffsetArray(a, 0:1, :,  CartesianIndices(()), 2:3) == OffsetArray(a, 0:1, :, 2:3)\n        @test OffsetArray(a, 0:1, :, 2:3, CartesianIndices(())) == OffsetArray(a, 0:1, :, 2:3)\n\n        # nested OffsetArrays\n        for offsets in [(1,1,1), big.((1,1,1))]\n            ob = OffsetArray(oa, offsets); ob2 = OffsetArray(oa, offsets...);\n            @test eltype(ob) === eltype(ob2) === Float64\n            @test axes(ob, 1) === axes(ob2, 1) === IdOffsetRange(Base.OneTo(2), 0)\n            @test axes(ob, 2) === axes(ob2, 2) === IdOffsetRange(Base.OneTo(2), 3)\n            @test axes(ob, 3) === axes(ob2, 3) === IdOffsetRange(Base.OneTo(2), 2)\n        end\n\n        indices = (-1:1, -7:7, -1:2, -5:5, -1:1, -3:3, -2:2, -1:1)\n        y = OffsetArray{Float64}(undef, indices...);\n        @test axes(y) === axes(OffsetArray{Float64}(undef, indices))\n        @test axes(y) === axes(OffsetArray{Float64, length(indices)}(undef, indices...))\n        @test no_offset_axes(y) == (-1:1, -7:7, -1:2, -5:5, -1:1, -3:3, -2:2, -1:1)\n        @test eltype(y) === Float64\n\n        @test_throws ArgumentError OffsetArray{Float64, 2}(undef, indices)\n        @test_throws ArgumentError OffsetArray(y, indices[1:2])\n\n        @test ndims(OffsetArray(zeros(), ())) == 0\n        @test Base.axes1(OffsetArray(zeros(), ())) === OffsetArrays.IdOffsetRange(Base.OneTo(1))\n\n        @testset \"convenience constructors\" begin\n            ax = (2:3, 4:5)\n\n            for f in (zeros, ones)\n                a = f(Float64, ax)\n                @test no_offset_axes(a) == ax\n                @test eltype(a) == Float64\n            end\n\n            for f in (trues, falses)\n                a = f(ax)\n                @test no_offset_axes(a) == ax\n                @test eltype(a) == Bool\n            end\n        end\n\n        # eltype of an OffsetArray should match that of the parent (issue #162)\n        @test_throws TypeError OffsetArray{Float64,2,Matrix{ComplexF64}}\n        # ndim of an OffsetArray should match that of the parent\n        @test_throws TypeError OffsetArray{Float64,3,Matrix{Float64}}\n\n        # should throw a TypeError if the offsets can not be converted to Ints\n        @test_throws TypeError OffsetVector{Int,Vector{Int}}(zeros(Int,2), (WeirdInteger(1),))\n    end\n\n    @testset \"custom range types\" begin\n        @testset \"EllipsisNotation\" begin\n            @testset \"Vector\" begin\n                v = rand(5)\n                @test axes(OffsetArray(v, ..)) == axes(v)\n                @test OffsetArray(v, ..) == OffsetArray(v, :)\n                @test axes(OffsetVector(v, ..)) == axes(v)\n                @test OffsetVector(v, ..) == OffsetVector(v, :)\n\n                @test no_offset_axes(OffsetArray(v, .., 2:6)) == (2:6, )\n                @test OffsetArray(v, .., 2:6) == OffsetArray(v, 2:6)\n                @test no_offset_axes(OffsetVector(v, .., 2:6)) == (2:6, )\n                @test OffsetVector(v, .., 2:6) == OffsetVector(v, 2:6)\n            end\n            @testset \"Matrix\" begin\n                m = rand(2, 2)\n                @test axes(OffsetArray(m, ..)) == axes(m)\n                @test OffsetArray(m, ..) == OffsetArray(m, :, :)\n                @test axes(OffsetMatrix(m, ..)) == axes(m)\n                @test OffsetMatrix(m, ..) == OffsetMatrix(m, :, :)\n\n                @test no_offset_axes(OffsetArray(m, .., 2:3)) == (axes(m, 1), 2:3)\n                @test OffsetArray(m, .., 2:3) == OffsetArray(m, :, 2:3)\n                @test no_offset_axes(OffsetMatrix(m, .., 2:3)) == (axes(m, 1), 2:3)\n                @test OffsetMatrix(m, .., 2:3) == OffsetMatrix(m, :, 2:3)\n\n                @test no_offset_axes(OffsetArray(m, .., 2:3, 3:4)) == (2:3, 3:4)\n                @test OffsetArray(m, .., 2:3, 3:4) == OffsetArray(m, 2:3, 3:4)\n                @test no_offset_axes(OffsetMatrix(m, .., 2:3, 3:4)) == (2:3, 3:4)\n                @test OffsetMatrix(m, .., 2:3, 3:4) == OffsetMatrix(m, 2:3, 3:4)\n            end\n            @testset \"3D Array\" begin\n                a = rand(2, 2, 2)\n                @test axes(OffsetArray(a, ..)) == axes(a)\n                @test OffsetArray(a, ..) == OffsetArray(a, :, :, :)\n\n                @test no_offset_axes(OffsetArray(a, .., 2:3)) == (axes(a)[1:2]..., 2:3)\n                @test OffsetArray(a, .., 2:3) == OffsetArray(a, :, :, 2:3)\n\n                @test no_offset_axes(OffsetArray(a, .., 2:3, 3:4)) == (axes(a, 1), 2:3, 3:4)\n                @test OffsetArray(a, .., 2:3, 3:4) == OffsetArray(a, :, 2:3, 3:4)\n\n                @test no_offset_axes(OffsetArray(a, 2:3, .., 3:4)) == (2:3, axes(a, 2), 3:4)\n                @test OffsetArray(a, 2:3, .., 3:4) == OffsetArray(a, 2:3, :, 3:4)\n\n                @test no_offset_axes(OffsetArray(a, .., 4:5, 2:3, 3:4)) == (4:5, 2:3, 3:4)\n                @test OffsetArray(a, .., 4:5, 2:3, 3:4) == OffsetArray(a, 4:5, 2:3, 3:4)\n            end\n        end\n        @testset \"ZeroBasedIndexing\" begin\n            Base.to_indices(A, inds, ::Tuple{ZeroBasedIndexing}) = map(x -> 0:length(x) - 1, inds)\n\n            a = zeros(3,3)\n            oa = OffsetArray(a, ZeroBasedIndexing())\n            @test no_offset_axes(oa) == (0:2, 0:2)\n        end\n        @testset \"TupleOfRanges\" begin\n            Base.to_indices(A, inds, t::Tuple{TupleOfRanges{N}}) where {N} = t\n            OffsetArrays.AxisConversionStyle(::Type{TupleOfRanges{N}}) where {N} =\n                OffsetArrays.TupleOfRanges()\n\n            Base.convert(::Type{Tuple{Vararg{AbstractUnitRange{Int}}}}, t::TupleOfRanges) = t.x\n\n            a = zeros(3,3)\n            inds = TupleOfRanges((3:5, 2:4))\n            oa = OffsetArray(a, inds)\n            @test no_offset_axes(oa) == inds.x\n        end\n        @testset \"NewColon\" begin\n            Base.to_indices(A, inds, t::Tuple{NewColon,Vararg{Any}}) =\n                (_uncolon(inds, t), to_indices(A, Base.tail(inds), Base.tail(t))...)\n\n            _uncolon(inds::Tuple{}, I::Tuple{NewColon, Vararg{Any}}) = OneTo(1)\n            _uncolon(inds::Tuple, I::Tuple{NewColon, Vararg{Any}}) = inds[1]\n\n            a = zeros(3, 3)\n            oa = OffsetArray(a, (NewColon(), 2:4))\n            @test no_offset_axes(oa) == (axes(a,1), 2:4)\n        end\n    end\n\n    @testset \"Offset range construction\" begin\n        r = -2:5\n        for AT in Any[OffsetArray, OffsetVector]\n            y = AT(r, r)\n            @test no_offset_axes(y) == (r,)\n            @test step(y) == step(r)\n            y = AT(r, (r,))\n            @test no_offset_axes(y) == (r,)\n            y = AT(r, CartesianIndices((r, )))\n            @test no_offset_axes(y) == (r, )\n        end\n    end\n\n    @testset \"size/length\" begin\n        for p in Any[SA[1,2,3,4], 1:4, [1:4;]]\n            for A in Any[OffsetArray(p, 4),\n                    OffsetArray(reshape(p, 2, 2), 3, 4),\n                    OffsetArray(reshape(p, 2, 1, 2), 3, 0, 4),\n                    OffsetArray(reshape(p, Val(1)), 2)]\n                @test size(A) == size(parent(A))\n                @test length(A) == length(parent(A))\n            end\n        end\n    end\nend\n\n@testset \"Axes supplied to constructor correspond to final result\" begin\n    # Ref https://github.com/JuliaArrays/OffsetArrays.jl/pull/65#issuecomment-457181268\n    B = BidirectionalVector([1, 2, 3], -2)\n    A = OffsetArray(B, -1:1)\n    @test no_offset_axes(A) == (-1:1,)\nend\n\n@testset \"unwrap\" begin\n    for A in [ones(2, 2), ones(2:3, 2:3), ZeroBasedRange(1:4)]\n        p, f = OffsetArrays.unwrap(A)\n        @test f(map(y -> y^2, p)) == A.^2\n    end\nend\n\n@testset \"Traits\" begin\n    A0 = [1 3; 2 4]\n    A = OffsetArray(A0, (-1,2))                   # IndexLinear\n    S = OffsetArray(view(A0, 1:2, 1:2), (-1,2))   # IndexCartesian\n    @test axes(A) === axes(S)\n    @test no_offset_axes(A) == no_offset_axes(S) == (0:1, 3:4)\n    @test axes(A, 1) === OffsetArrays.IdOffsetRange(Base.OneTo(2), -1)\n    @test size(A) == size(A0)\n    @test size(A, 1) == size(A0, 1)\n    @test length(A) == length(A0)\n    @test A == OffsetArray(A0, 0:1, 3:4)\n    @test_throws DimensionMismatch OffsetArray(A0, 0:2, 3:4)\n    @test_throws DimensionMismatch OffsetArray(A0, 0:1, 2:4)\n    @test eachindex(IndexLinear(), A) == eachindex(IndexLinear(), parent(A))\n    @test eachindex(IndexCartesian(), A) == CartesianIndices(A) == CartesianIndices(axes(A))\n    @test eachindex(S) == eachindex(IndexCartesian(), S) == CartesianIndices(S)\n    @test eachindex(IndexLinear(), S) == eachindex(IndexLinear(), A0)\n    A = ones(5:6)\n    @test eachindex(IndexLinear(), A) === axes(A, 1)\n\n    A = OffsetArray(big(1):big(2), 1)\n    B = OffsetArray(1:2, 1)\n    @test CartesianIndices(A) == CartesianIndices(B)\n    @test LinearIndices(A) == LinearIndices(B)\n    @test eachindex(A) == eachindex(B)\nend\n\n@testset \"Scalar indexing\" begin\n    A0 = [1 3; 2 4]\n    A = OffsetArray(A0, (-1,2))\n    S = OffsetArray(view(A0, 1:2, 1:2), (-1,2))\n\n    @test @inferred(A[0,3]) == @inferred(A[0,3,1]) == @inferred(A[1]) == @inferred(S[0,3]) == @inferred(S[0,3,1]) == @inferred(S[1]) == 1\n    @test A[1,3] == A[1,3,1] == A[2] == S[1,3] == S[1,3,1] == S[2] == 2\n    @test A[0,4] == A[0,4,1] == A[3] == S[0,4] == S[0,4,1] == S[3] == 3\n    @test A[1,4] == A[1,4,1] == A[4] == S[1,4] == S[1,4,1] == S[4] == 4\n    @test @inbounds(A[0,3]) == @inbounds(A[0,3,1]) == @inbounds(A[1]) == @inbounds(S[0,3]) == @inbounds(S[0,3,1]) == @inbounds(S[1]) == 1\n    @test @inbounds(A[1,3]) == @inbounds(A[1,3,1]) == @inbounds(A[2]) == @inbounds(S[1,3]) == @inbounds(S[1,3,1]) == @inbounds(S[2]) == 2\n    @test @inbounds(A[0,4]) == @inbounds(A[0,4,1]) == @inbounds(A[3]) == @inbounds(S[0,4]) == @inbounds(S[0,4,1]) == @inbounds(S[3]) == 3\n    @test @inbounds(A[1,4]) == @inbounds(A[1,4,1]) == @inbounds(A[4]) == @inbounds(S[1,4]) == @inbounds(S[1,4,1]) == @inbounds(S[4]) == 4\n    @test_throws BoundsError(A, (1,1)) A[1,1]\n    @test_throws BoundsError(A, (1,1)) A[1,1] = 4\n    @test_throws BoundsError(S, (1,1)) S[1,1]\n    @test_throws BoundsError(S, (1,1)) S[1,1] = 4\n    @test_throws BoundsError(A, (0,3,2)) A[0,3,2]\n    @test_throws BoundsError(A, (0,3,2)) A[0,3,2] = 4\n    @test_throws BoundsError(A, (0,3,0)) A[0,3,0]\n    @test_throws BoundsError(A, (0,3,0)) A[0,3,0] = 4\n    Ac = copy(A)\n    Ac[0,3] = 10\n    @test Ac[0,3] == 10\n    Ac[0,3,1] = 11\n    @test Ac[0,3] == 11\n    @inbounds Ac[0,3,1] = 12\n    @test Ac[0,3] == 12\n\n    y = OffsetArray{Float64}(undef, -1:1, -7:7, -3:-1, -5:5, -1:1, -3:3, -2:2, -1:1)\n    y[-1,-7,-3,-5,-1,-3,-2,-1] = 14\n    y[-1,-7,-3,-5,-1,-3,-2,-1] += 5\n    @test y[-1,-7,-3,-5,-1,-3,-2,-1] == 19\n\n    @testset \"setindex!\" begin\n        A = OffsetArray(ones(2,2), 1:2, 1:2)\n        @test setindex!(A, 2, 1, 1) === A\n        @test A[1,1] == 2\n        @test setindex!(A, 2, 1) === A\n        @test A[1] == 2\n\n        v = OffsetArray(ones(3), 4:6)\n        @test setindex!(A, 2, 4) === A\n        @test A[4] == 2\n    end\n\n    @testset \"Zero-index indexing (#194)\" begin\n        @test OffsetArray([6], 2:2)[] == 6\n        @test OffsetArray(fill(6, 1, 1), 2:2, 3:3)[] == 6\n        @test OffsetArray(fill(6))[] == 6\n        @test_throws BoundsError OffsetArray([6,7], 2:3)[]\n        @test_throws BoundsError OffsetArray([6 7], 2:2, 2:3)[]\n        @test_throws BoundsError OffsetArray([], 2:1)[]\n    end\nend\n\n_comp(x::Integer, y::Integer) = x == y\n_comp(x::Any, y::Any) = isapprox(Real(x), Real(y), atol = 1e-14, rtol = 1e-8)\nfunction test_indexing_axes_and_vals(r1, r2)\n    r12 = r1[r2]\n    if axes(r12, 1) != axes(r2, 1)\n        @show r1 r2 r12 axes(r12, 1) axes(r2, 1)\n    end\n    @test axes(r12, 1) == axes(r2, 1)\n\n    if axes(r12, 1) == axes(r2, 1)\n        res1 = try\n            _comp(first(r12), r1[first(r2)])\n        catch\n            @show r1 r2\n            rethrow()\n        end\n        res2 = try\n            _comp(last(r12), r1[last(r2)])\n        catch\n            @show r1 r2\n            rethrow()\n        end\n        if !(res1 & res2)\n            @show r1 r2\n        end\n        @test res1\n        @test res2\n        for i in eachindex(r2)\n            @test _comp(r12[i], r1[r2[i]])\n        end\n    end\nend\n\n@testset \"Vector indexing\" begin\n    A0 = [1 3; 2 4]\n    A = OffsetArray(A0, (-1,2))\n    S = OffsetArray(view(A0, 1:2, 1:2), (-1,2))\n\n    @test A[:, 3] == S[:, 3] == OffsetArray([1,2], (A.offsets[1],))\n    @test A[:, 4] == S[:, 4] == OffsetArray([3,4], (A.offsets[1],))\n    @test_throws BoundsError A[:, 1]\n    @test_throws BoundsError S[:, 1]\n    @test A[0, :] == S[0, :] == OffsetArray([1,3], (A.offsets[2],))\n    @test A[1, :] == S[1, :] == OffsetArray([2,4], (A.offsets[2],))\n    @test_throws BoundsError A[2, :]\n    @test_throws BoundsError S[2, :]\n    @test A[0:1, 3] == S[0:1, 3] == [1,2]\n    @test A[[1,0], 3] == S[[1,0], 3] == [2,1]\n    @test A[0, 3:4] == S[0, 3:4] == [1,3]\n    @test A[1, [4,3]] == S[1, [4,3]] == [4,2]\n    @test A[:, :] == S[:, :] == A\n\n    # Indexing a nD OffsetArray with n colons preserves the type\n    r1 = OffsetArray(IdentityUnitRange(100:1000), 3)\n    @test r1[:] === r1\n\n    # In general with more colons than dimensions,\n    # the type might not be preserved but the values and the leading axes should be\n    r2 = r1[:,:]\n    @test axes(r2, 1) == axes(r1, 1)\n    @test same_value(r1, r2)\n\n    s = @SVector[i for i in 1:3]\n    so = OffsetArray(s, 3)\n    @test so[:] === so\n\n    a = Ones(3, 2, 1)\n    ao = OffsetArray(a, axes(a))\n    @test ao[:,:,:] === ao\n    @test same_value(ao[:], ao)\n    @test same_value(ao[:,:], ao)\n\n    # Indexing an nD OffsetArray with one Colon preserves only the values.\n    # This uses linear indexing\n    a = ones(2:3, 2:3)\n    b = a[:]\n    @test same_value(a, b)\n\n    vals = (1,2,3,4,5,6,7,8)\n    s = SArray{Tuple{2,2,2},Int,3,8}(vals)\n    so = OffsetArray(s, axes(s));\n    so2 = so[:]\n    @test same_value(so2, s)\n\n    # Test r1[inds] for various combinations of types\n\n    # AbstractArrays with 1-based indices\n    indslist1 = Any[\n            OffsetArray(5:8, 0),\n            # This currently errors for IdentityUnitRange\n            # see https://github.com/JuliaLang/julia/issues/39997\n            # OffsetArray(big(5):big(80), 0),\n            OffsetArray(5:2:9, 0),\n            OffsetArray(9:-2:5, 0),\n            OffsetArray(IdentityUnitRange(5:8), -4),\n            OffsetArray(IdOffsetRange(5:8), 0),\n            ]\n\n    # AbstractRanges with 1-based indices\n    indslist2 = Any[\n            5:8,\n            # This currently errors for IdentityUnitRange\n            # see https://github.com/JuliaLang/julia/issues/39997\n            # big(5):big(80),\n            5:2:9,\n            9:-2:5,\n            IdOffsetRange(5:8),\n            IdOffsetRange(ZeroBasedUnitRange(4:7), 1),\n            ]\n\n    for r1 in Any[\n        # AbstractArrays\n        collect(1:100),\n        reshape(collect(-1:100), -1:100),\n        collect(reshape(1:400, 20, 20)),\n        reshape(collect(1:21^2), -10:10, -10:10),\n\n        # OffsetRanges\n        OffsetArray(10:1000, 0), # 1-based index\n        OffsetArray(UnitRange(10.0, 1000.0), 0), # 1-based index\n        OffsetArray(10:3:1000, 3), # offset index\n        OffsetArray(10.0:3:1000.0, 0), # 1-based index\n        OffsetArray(10.0:3:1000.0, 3), # offset index\n        OffsetArray(IdOffsetRange(10:1000, 1), -1), # 1-based index\n        OffsetArray(IdOffsetRange(10:1000, 1), 3), # offset index\n        OffsetArray(IdOffsetRange(IdOffsetRange(10:1000, -4), 1), 3), # 1-based index\n        OffsetArray(IdOffsetRange(IdOffsetRange(10:1000, -1), 1), 3), # offset index\n\n        # AbstractRanges\n        Base.OneTo(1000),\n        CustomRange(Base.OneTo(1000)),\n        Slice(Base.OneTo(1000)),\n        1:1000,\n        UnitRange(1.0, 1000.0),\n        1:3:1000,\n        1000:-3:1,\n        1.0:3.0:1000.0,\n        StepRangeLen(Float64(1), Float64(1000), 1000),\n        LinRange(1, 1000, 1000),\n        Base.Slice(Base.OneTo(1000)), # 1-based index\n        IdentityUnitRange(Base.OneTo(1000)), # 1-based index\n        IdOffsetRange(Base.OneTo(1000)), # 1-based index\n        IdentityUnitRange(2:1000), # offset index\n        IdOffsetRange(ZeroBasedUnitRange(1:1000), 1), # 1-based index\n        IdOffsetRange(ZeroBasedUnitRange(1:1000), 2), # offset index\n        ZeroBasedUnitRange(1:1000), # offset range\n        ZeroBasedRange(1:1000), # offset range\n        ZeroBasedRange(1:1:1000), # offset range\n        CustomRange(ZeroBasedRange(1:1:1000)), # offset range\n        ]\n\n        # AbstractArrays with 1-based indices\n        for r2 in indslist1\n            test_indexing_axes_and_vals(r1, r2)\n            test_indexing_axes_and_vals(r1, collect(r2))\n        end\n\n        # AbstractRanges with 1-based indices\n        for r2 in indslist2\n\n            test_indexing_axes_and_vals(r1, r2)\n            test_indexing_axes_and_vals(r1, collect(r2))\n\n            if r1 isa AbstractRange && !(r1 isa CustomRange) && axes(r2, 1) isa Base.OneTo\n                @test r1[r2] isa AbstractRange\n            end\n        end\n    end\n\n    # Indexing with IdentityUnitRange(::Base.OneTo) or Base.Slice(::OneTo) is special.\n    # This is because axes(::IdentityUnitRange{<:Base.OneTo}, 1) isa Base.OneTo, and not an IdentityUnitRange.\n    # These therefore may pass through no_offset_view unchanged.\n    # This had led to a stack-overflow in indexing, as getindex was using no_offset_view.\n    # Issue 209\n    for r1 in Any[\n        # This set of tests is for ranges r1 that have 1-based indices\n        UnitRange(1.0, 99.0),\n        1:99,\n        Base.OneTo(99),\n        1:1:99,\n        99:-1:1,\n        1.0:1.0:99.0,\n        StepRangeLen(Float64(1), Float64(99), 99),\n        LinRange(1, 99, 99),\n        Base.Slice(Base.OneTo(99)),\n        IdentityUnitRange(Base.OneTo(99)),\n        IdOffsetRange(Base.OneTo(99)),\n        ]\n\n        for r2 in Any[\n            IdentityUnitRange(Base.OneTo(3)),\n            Base.Slice(Base.OneTo(3)),\n            IdOffsetRange(Base.OneTo(3)),\n            ]\n\n            test_indexing_axes_and_vals(r1, r2)\n            test_indexing_axes_and_vals(r1, collect(r2))\n            if axes(r2, 1) isa Base.OneTo\n                @test r1[r2] isa AbstractRange\n            end\n        end\n    end\nend\n\n@testset \"Vector indexing with offset ranges\" begin\n    r = OffsetArray(8:10, -1:1)\n    r1 = r[0:1]\n    @test r1 === 9:10\n    r1 = (8:10)[OffsetArray(1:2, -5:-4)]\n    @test no_offset_axes(r1) == (-5:-4,)\n    @test no_offset_view(r1) == 8:9\n    r1 = OffsetArray(8:10, -1:1)[OffsetArray(0:1, -5:-4)]\n    @test no_offset_axes(r1) == (-5:-4,)\n    @test no_offset_view(r1) == 9:10\n\n    a = OffsetVector(3:4, 10:11)\n    ax = OffsetArrays.IdOffsetRange(5:6, 5)\n    @test axes(a[ax]) == axes(ax)\n    for i in axes(ax,1)\n        @test a[ax[i]] == a[ax][i]\n    end\n\n    ax = IdentityUnitRange(10:11)\n    @test axes(a[ax]) == axes(ax)\n    for i in axes(ax,1)\n        @test a[ax[i]] == a[ax][i]\n    end\n\n    # AbstractArrays with offset axes\n    indslist1 = Any[OffsetArray(5:9, 40),\n            OffsetArray(5:2:9, 40),\n            OffsetArray(9:-2:5, 40),\n            OffsetArray(IdentityUnitRange(5:8), 2),\n            OffsetArray(IdOffsetRange(5:8, 1), 3),\n            OffsetArray(IdOffsetRange(IdOffsetRange(5:8, 4), 1), 3),\n            OffsetArray(IdOffsetRange(IdentityUnitRange(5:8), 1), 3),\n            OffsetArray(IdentityUnitRange(IdOffsetRange(5:8, 1)), 3),\n            ]\n\n    # AbstractRanges with offset axes\n    indslist2 = Any[IdOffsetRange(5:8, 1),\n            IdentityUnitRange(5:8),\n            IdOffsetRange(Base.OneTo(3), 4),\n            IdOffsetRange(IdOffsetRange(5:8, 2), 1),\n            IdOffsetRange(IdOffsetRange(IdOffsetRange(5:8, -1), 2), 1),\n            IdentityUnitRange(IdOffsetRange(1:4, 5)),\n            IdOffsetRange(IdentityUnitRange(15:20), -2),\n            ZeroBasedUnitRange(5:8),\n            ZeroBasedRange(5:8),\n            ZeroBasedRange(5:2:9),\n            ZeroBasedRange(9:-2:5),\n            ]\n\n    for r1 in Any[\n        # AbstractArrays\n        collect(1:100),\n        reshape(collect(-1:100), -1:100),\n        collect(reshape(1:400, 20, 20)),\n        reshape(collect(1:21^2), -10:10, -10:10),\n\n        # OffsetRanges\n        OffsetArray(10:1000, 0), # 1-based index\n        OffsetArray(UnitRange(10.0, 1000.0), 0), # 1-based index\n        OffsetArray(10:1000, 3), # offset index\n        OffsetArray(10:3:1000, 0), # 1-based index\n        OffsetArray(10:3:1000, 3), # offset index\n        OffsetArray(10.0:3:1000.0, 0), # 1-based index\n        OffsetArray(10.0:3:1000.0, 3), # offset index\n        OffsetArray(IdOffsetRange(10:1000, -3), 3), # 1-based index\n        OffsetArray(IdOffsetRange(10:1000, 1), 3), # offset index\n        OffsetArray(IdOffsetRange(IdOffsetRange(10:1000, -4), 1), 3), # 1-based index\n        OffsetArray(IdOffsetRange(IdOffsetRange(10:1000, -1), 1), 3), # offset index\n\n        # AbstractRanges\n        Base.OneTo(1000),\n        Slice(Base.OneTo(1000)),\n        CustomRange(Base.OneTo(1000)),\n        1:1000,\n        UnitRange(1.0, 1000.0),\n        1:2:2000,\n        2000:-1:1,\n        1.0:2.0:2000.0,\n        StepRangeLen(Float64(1), Float64(1000), 1000),\n        LinRange(1.0, 2000.0, 2000),\n        Base.Slice(Base.OneTo(1000)), # 1-based index\n        IdOffsetRange(Base.OneTo(1000)), # 1-based index\n        IdOffsetRange(1:1000, 0), # 1-based index\n        IdOffsetRange(Base.OneTo(1000), 4), # offset index\n        IdOffsetRange(1:1000, 4), # offset index\n        IdOffsetRange(ZeroBasedUnitRange(1:1000), 1), # 1-based index\n        IdOffsetRange(ZeroBasedUnitRange(1:1000), 2), # offset index\n        IdentityUnitRange(ZeroBasedUnitRange(1:1000)), # 1-based index\n        IdentityUnitRange(5:1000), # offset index\n        ZeroBasedUnitRange(1:1000), # offset index\n        ZeroBasedRange(1:1000), # offset index\n        ZeroBasedRange(1:1:1000), # offset index\n        ZeroBasedUnitRange(IdentityUnitRange(1:1000)), # offset index\n        CustomRange(ZeroBasedUnitRange(IdentityUnitRange(1:1000))), # offset index\n        ]\n\n        # AbstractArrays with offset axes\n        for r2 in indslist1\n            test_indexing_axes_and_vals(r1, r2)\n            r2_dense = OffsetArray(collect(r2), axes(r2))\n            test_indexing_axes_and_vals(r1, r2_dense)\n        end\n\n        # AbstractRanges with offset axes\n        for r2 in indslist2\n\n            test_indexing_axes_and_vals(r1, r2)\n            r2_dense = OffsetArray(collect(r2), axes(r2))\n            test_indexing_axes_and_vals(r1, r2_dense)\n\n            # This might not hold for all ranges, but holds for the known ones being tested here\n            if r1 isa AbstractUnitRange{<:Integer} && r2 isa AbstractUnitRange{<:Integer}\n                @test r1[r2] isa AbstractUnitRange{<:Integer}\n            end\n        end\n    end\nend\n\n@testset \"LinearIndexing\" begin\n    r = OffsetArray(ZeroBasedRange(3:4), 1);\n    @test LinearIndices(r) == axes(r,1)\n    r = OffsetArray(ZeroBasedRange(3:4), 2);\n    @test LinearIndices(r) == axes(r,1)\nend\n\n@testset \"CartesianIndexing\" begin\n    A0 = [1 3; 2 4]\n    A = OffsetArray(A0, (-1,2))\n    S = OffsetArray(view(A0, 1:2, 1:2), (-1,2))\n\n    @test A[CartesianIndex((0,3))] == S[CartesianIndex((0,3))] == 1\n    @test A[CartesianIndex((0,3)),1] == S[CartesianIndex((0,3)),1] == 1\n    @test @inbounds(A[CartesianIndex((0,3))]) == @inbounds(S[CartesianIndex((0,3))]) == 1\n    @test @inbounds(A[CartesianIndex((0,3)),1]) == @inbounds(S[CartesianIndex((0,3)),1]) == 1\n    @test_throws BoundsError A[CartesianIndex(1,1)]\n    @test_throws BoundsError A[CartesianIndex(1,1),0]\n    @test_throws BoundsError A[CartesianIndex(1,1),2]\n    @test_throws BoundsError S[CartesianIndex(1,1)]\n    @test_throws BoundsError S[CartesianIndex(1,1),0]\n    @test_throws BoundsError S[CartesianIndex(1,1),2]\n    @test eachindex(A) == 1:4\n    @test eachindex(S) == CartesianIndices(IdentityUnitRange.((0:1,3:4)))\nend\n\n@testset \"IdentityUnitRange indexing\" begin\n    # 155\n    a = OffsetVector(3:4, 2:3)\n    ax = IdentityUnitRange(2:3)\n    @test a[ax[2]] == a[ax][2]\n\n    s = -2:2:4\n    r = 5:8\n    y = OffsetArray(s, r)\n    @test no_offset_axes(y) == (r,)\n    @test step(y) == step(s)\n\n    a = OffsetVector(3:4, 10:11)\n    ax = OffsetArrays.IdOffsetRange(5:6, 5)\n    @test axes(a[ax]) == axes(ax)\n    for i in axes(ax,1)\n        @test a[ax[i]] == a[ax][i]\n    end\n\n    ax = IdentityUnitRange(10:11)\n    @test axes(a[ax]) == axes(ax)\n    for i in axes(ax,1)\n        @test a[ax[i]] == a[ax][i]\n    end\nend\n\n@testset \"view\" begin\n    A0 = [1 3; 2 4]\n    A = OffsetArray(A0, (-1,2))\n\n    S = view(A, :, 3)\n    @test S == OffsetArray([1,2], (A.offsets[1],))\n    @test S[0] == 1\n    @test S[1] == 2\n    @test_throws BoundsError S[2]\n    @test axes(S) == (IdentityUnitRange(0:1),)\n    S = view(A, 0, :)\n    @test S == OffsetArray([1,3], (A.offsets[2],))\n    @test S[3] == 1\n    @test S[4] == 3\n    @test_throws BoundsError S[1]\n    @test axes(S) == (IdentityUnitRange(3:4),)\n    S = view(A, 0:0, 4)\n    @test S == [3]\n    @test S[1] == 3\n    @test_throws BoundsError S[0]\n    @test axes(S) === (Base.OneTo(1),)\n    S = view(A, 1, 3:4)\n    @test S == [2,4]\n    @test S[1] == 2\n    @test S[2] == 4\n    @test_throws BoundsError S[3]\n    @test axes(S) === (Base.OneTo(2),)\n    S = view(A, :, :)\n    @test S == A\n    @test S[0,3] == S[1] == 1\n    @test S[1,3] == S[2] == 2\n    @test S[0,4] == S[3] == 3\n    @test S[1,4] == S[4] == 4\n    @test_throws BoundsError S[1,1]\n    @test axes(S) == IdentityUnitRange.((0:1, 3:4))\n    S = view(A, axes(A)...)\n    @test S == A\n    @test S[0,3] == S[1] == 1\n    @test S[1,3] == S[2] == 2\n    @test S[0,4] == S[3] == 3\n    @test S[1,4] == S[4] == 4\n    @test_throws BoundsError S[1,1]\n    @test no_offset_axes(S) == (0:1, 3:4)\n    # issue 100\n    S = view(A, axes(A, 1), 3)\n    @test S == A[:, 3]\n    @test S[0] == 1\n    @test S[1] == 2\n    @test_throws BoundsError S[length(S)]\n    @test no_offset_axes(S) == (0:1, )\n    # issue 100\n    S = view(A, 1, axes(A, 2))\n    @test S == A[1, :]\n    @test S[3] == 2\n    @test S[4] == 4\n    @test_throws BoundsError S[1]\n    @test no_offset_axes(S) == (3:4, )\n\n    # issue 133\n    r = OffsetArrays.IdOffsetRange(1:2, -1)\n    v1 = view(A, r, 3)\n    @test v1[0] == 1\n    @test v1[1] == 2\n    @test axes(v1, 1) == axes(r, 1)\n    v2 = view(A, UnitRange(r), 3)\n    for (indflat, indoffset) in enumerate(r)\n        @test v1[indoffset] == v2[indflat]\n    end\n\n    # issue 133\n    r = OffsetArrays.IdOffsetRange(1:2, 2)\n    v1 = view(A, 1, r)\n    @test v1[3] == 2\n    @test v1[4] == 4\n    @test axes(v1, 1) == axes(r, 1)\n    v2 = view(A, 1, UnitRange(r))\n    for (indflat, indoffset) in enumerate(r)\n        @test v1[indoffset] == v2[indflat]\n    end\n\n    # issue 133\n    a12 = zeros(3:8, 3:4)\n    r = OffsetArrays.IdOffsetRange(Base.OneTo(3), 5)\n    a12[r, 4] .= 3\n    @test all(a12[r, 4] .== 3)\n    @test all(a12[UnitRange(r), 4] .== 3)\n\n    A0 = collect(reshape(1:24, 2, 3, 4))\n    A = OffsetArray(A0, (-1,2,1))\n    S = view(A, axes(A, 1), 3:4, axes(A, 3))\n    @test S == A[:, 3:4, :]\n    @test S[0, 1, 2] == A[0, 3, 2]\n    @test S[0, 2, 2] == A[0, 4, 2]\n    @test S[1, 1, 2] == A[1, 3, 2]\n    @test no_offset_axes(S) == (0:1, Base.OneTo(2), 2:5)\n\n    # issue #186\n    a = reshape(1:12, 3, 4)\n    r = OffsetArrays.IdOffsetRange(3:4)\n    av = view(a, :, r)\n    @test av == a[:, 3:4]\n    @test axes(av) == (axes(a,1), axes(r,1))\n    r = OffsetArrays.IdOffsetRange(1:2,2)\n    av = view(a, :, r)\n    @test no_offset_view(av) == a[:, 3:4]\n    @test axes(av) == (axes(a,1), axes(r,1))\n    r = OffsetArrays.IdOffsetRange(2:3)\n    av1d = view(a, r, 3)\n    @test av1d == a[2:3, 3]\n    @test axes(av1d) == (axes(r,1),)\n    r = OffsetArrays.IdOffsetRange(Base.OneTo(2), 1)\n    av1d = view(a, r, 3)\n    @test no_offset_view(av1d) == a[2:3, 3]\n    @test axes(av1d) == (axes(r,1),)\n\n    # fix IdOffsetRange(::IdOffsetRange, offset) nesting from #178\n    b = 1:20\n    bov = OffsetArray(view(b, 3:4), 3:4)\n    c = @view b[bov]\n    @test same_value(c, 3:4)\n    @test no_offset_axes(c,1) == 3:4\n    d = OffsetArray(c, 1:2)\n    @test same_value(d, c)\n    @test axes(d,1) == 1:2\n\n    # Issue 128\n    a = OffsetArray(1:3, 0:2);\n    b = @view a[0]\n    @test b[] == b[1] == 1\n\n    a = reshape(1:16, 4, 4);\n    for ax1 in (:, axes(a,1), UnitRange(axes(a,1))),\n        ax2 in (:, axes(a,2), UnitRange(axes(a,2)))\n            av = @view a[ax1, ax2]\n            av_nooffset = OffsetArrays.no_offset_view(av)\n            @test axes(av_nooffset) === axes(av)\n    end\nend\n\n@testset \"iteration\" begin\n    A0 = [1 3; 2 4]\n    A = OffsetArray(A0, (-1,2))\n\n    let a\n        for (a,d) in zip(A, A0)\n            @test a == d\n        end\n    end\n\n    v = ones(10)\n    for r in Any[1:1:10, 1:10], s in Any[r, collect(r)]\n        so = OffsetArray(s)\n        @test Float64[v[i] for i in s] == Float64[v[i] for i in so]\n    end\nend\n\n@testset \"show/summary\" begin\n    A0 = [1 3; 2 4]\n    A = OffsetArray(A0, (-1,2))\n    S = OffsetArray(view(A0, 1:2, 1:2), (-1,2))\n\n    @test sprint(show, A) == \"[1 3; 2 4]\"\n    @test sprint(show, S) == \"[1 3; 2 4]\"\n    strs = split(strip(sprint(show, MIME(\"text/plain\"), A)), '\\n')\n    @test strs[2] == \" 1  3\"\n    @test strs[3] == \" 2  4\"\n    v = OffsetArray(rand(3), (-2,))\n    @test sprint(show, v) == sprint(show, parent(v))\n    io = IOBuffer()\n    function cmp_showf(printfunc, io, A)\n        ioc = IOContext(io, :limit=>true, :compact=>true)\n        printfunc(ioc, A)\n        str1 = String(take!(io))\n        printfunc(ioc, parent(A))\n        str2 = String(take!(io))\n        @test str1 == str2\n    end\n    cmp_showf(Base.print_matrix, io, OffsetArray(rand(5,5), (10,-9)))       # rows&cols fit\n    cmp_showf(Base.print_matrix, io, OffsetArray(rand(10^3,5), (10,-9)))    # columns fit\n    cmp_showf(Base.print_matrix, io, OffsetArray(rand(5,10^3), (10,-9)))    # rows fit\n    cmp_showf(Base.print_matrix, io, OffsetArray(rand(10^3,10^3), (10,-9))) # neither fits\n\n    a = OffsetArray([1 2; 3 4], -1:0, 5:6)\n    shownsz = VERSION >= v\"1.2.0-DEV.229\" ? Base.dims2string(size(a))*' ' : \"\"\n    @test summary(a) == \"$(shownsz)OffsetArray(::$(typeof(parent(a))), -1:0, 5:6) with eltype $(Int) with indices -1:0×5:6\"\n    shownsz = VERSION >= v\"1.2.0-DEV.229\" ? Base.dims2string(size(view(a, :, 5)))*' ' : \"\"\n    @test summary(view(a, :, 5)) == \"$(shownsz)view(OffsetArray(::$(typeof(parent(a))), -1:0, 5:6), :, 5) with eltype $(Int) with indices -1:0\"\n    a = OffsetArray(reshape([1]))\n    @test summary(a) == \"0-dimensional OffsetArray(::$(typeof(parent(a)))) with eltype $(Int)\"\n\n    a = OffsetArray([1 2; 3 4], -1:0, 5:6)\n    io = IOBuffer()\n    show(io, axes(a, 1))\n    @test String(take!(io)) == \"IdOffsetRange(values=-1:0, indices=-1:0)\"   # not qualified because of the using OffsetArrays: IdOffsetRange at top\n    show(io, axes(a, 2))\n    @test String(take!(io)) == \"IdOffsetRange(values=5:6, indices=5:6)\"\n    rrtable = IdOffsetRange(values=7:9, indices=-1:1)\n    rrted = eval(Meta.parse(string(rrtable)))\n    @test pairs(rrtable) == pairs(rrted)\n\n    @test Base.inds2string(axes(a)) == Base.inds2string(map(UnitRange, axes(a)))\n    @test Base.inds2string((IdOffsetRange(3:4),)) == \"3:4\"\n    @test Base.inds2string((IdentityUnitRange(IdOffsetRange(3:4)),)) == \"3:4\"\n    # check that the following doesn't throw\n    @test Base.inds2string(()) isa Any\n\n    show(io, OffsetArray(3:5, 0:2))\n    @test String(take!(io)) == \"3:5 with indices 0:2\"\n\n    show(io, MIME\"text/plain\"(), OffsetArray(3:5, 0:2))\n    @test String(take!(io)) == \"3:5 with indices 0:2\"\n\n    # issue #198\n    for r in Any[axes(OffsetVector(1:10, -5), 1), 1:1:2, 1.0:1.0:2.0, 1:-1:-5]\n        a = OffsetVector(r, 5)\n        show(io, a)\n        @test String(take!(io)) == \"$r with indices $(UnitRange(axes(a,1)))\"\n    end\n\n    d = Diagonal([1,2,3])\n    Base.print_array(io, d)\n    s1 = String(take!(io))\n    od = OffsetArray(d, -1:1, 3:5)\n    Base.print_array(io, od)\n    s2 = String(take!(io))\n    @test s1 == s2\n\n    @test Base.replace_in_print_matrix(od, -1, 3, \" \") == Base.replace_in_print_matrix(d, 1, 1, \" \")\n    @test Base.replace_in_print_matrix(od, -1, 4, \" \") == Base.replace_in_print_matrix(d, 1, 2, \" \")\n\n    v = rand(3)\n    ov = OffsetArray(v, (-2,))\n    @test Base.replace_in_print_matrix(ov, -1, 1, \" \") == Base.replace_in_print_matrix(v, 1, 1, \" \")\n\n    # Avoid returning the value of toplevel if it is false\n    # showarg should only print values, it shouldn't return anything\n    @test Base.showarg(io, a, false) === nothing\n    # check the other case too for good measure\n    @test Base.showarg(io, a, true) === nothing\nend\n\n@testset \"readdlm/writedlm\" begin\n    A0 = [1 3; 2 4]\n    A = OffsetArray(A0, (-1,2))\n\n    io = IOBuffer()\n    writedlm(io, A)\n    seek(io, 0)\n    @test readdlm(io, eltype(A)) == parent(A)\nend\n\n@testset \"similar\" begin\n    A0 = [1 3; 2 4]\n    A = OffsetArray(A0, (-1,2))\n\n    B = similar(A, Float32)\n    @test isa(B, OffsetArray{Float32,2})\n    @test axes(B) === axes(A)\n    B = similar(A, (3,4))\n    @test isa(B, Array{Int,2})\n    @test size(B) == (3,4)\n    @test axes(B) === (Base.OneTo(3), Base.OneTo(4))\n    B = similar(A, (-3:3,1:4))\n    @test isa(B, OffsetArray{Int,2})\n    @test axes(B) == IdentityUnitRange.((-3:3, 1:4))\n    B = similar(parent(A), (-3:3,1:4))\n    @test isa(B, OffsetArray{Int,2})\n    @test axes(B) == IdentityUnitRange.((-3:3, 1:4))\n    @test isa([x for x in [1,2,3]], Vector{Int})\n    @test similar(Array{Int}, (0:0, 0:0)) isa OffsetArray{Int, 2}\n    @test similar(Array{Int}, (1, 1)) isa Matrix{Int}\n    @test similar(Array{Int}, (Base.OneTo(1), Base.OneTo(1))) isa Matrix{Int}\n    B = similar(Array{Int}, (0:0, 3))\n    @test isa(B, OffsetArray{Int, 2})\n    @test no_offset_axes(B) == (0:0, 1:3)\n\n    s = @SVector[i for i in 1:10]\n    so = OffsetArray(s, 4);\n    @test typeof(parent(similar(so))) == typeof(similar(s))\n    @test typeof(parent(similar(so, eltype(so), axes(so)))) == typeof(similar(s))\n\n    s = SArray{Tuple{2,2,2},Int,3,8}((1,2,3,4,5,6,7,8))\n    so = OffsetArray(s, 0, 0, 0)\n    A = similar(so)\n    @test A isa OffsetArray\n    @test parent(A) isa StaticArray\n    for ax in Any[(axes(s,1), axes(so)[2:3]...), (axes(so,1), axes(s)[2:3]...)]\n        A = similar(so, Int, ax)\n        @test A isa OffsetArray\n        @test parent(A) isa StaticArray\n        @test axes(A) == ax\n    end\n\n    # check with an unseen axis type\n    A = similar(ones(1), Int, ZeroBasedUnitRange(3:4), 4:5)\n    @test eltype(A) === Int\n    @test no_offset_axes(A) == (3:4, 4:5)\n    A = similar(ones(1), Int, IdOffsetRange(ZeroBasedUnitRange(3:4), 2), 4:5)\n    @test eltype(A) === Int\n    @test no_offset_axes(A) == (5:6, 4:5)\n    A = similar(ones(1), Int, IdOffsetRange(ZeroBasedUnitRange(3:4), 2), 4)\n    @test eltype(A) === Int\n    @test no_offset_axes(A) == (5:6, 1:4)\n\n    # test for similar(::Type, ax)\n    indsoffset = (IdOffsetRange(SOneTo(2), 2),)\n    A = similar(Array{Int}, indsoffset)\n    @test parent(A) isa StaticArray\n    @test no_offset_axes(A) == (3:4,)\n    A = similar(Array{Int}, (indsoffset..., SOneTo(3)))\n    @test parent(A) isa StaticArray\n    @test no_offset_axes(A) == (3:4, 1:3)\n\n    s = SArray{Tuple{2,2},Int,2,4}((1,2,3,4));\n    so = OffsetArray(s, 2, 2);\n    so2 = so .+ 1;\n    @test parent(so2) isa StaticArray\n\n    @test_throws MethodError similar(A, (:,))\n    @test_throws MethodError similar(A, (: ,:))\n    @test_throws MethodError similar(A, (: ,2))\n    @test_throws MethodError similar(A, Float64, (: ,:))\n    @test_throws MethodError similar(A, Float64, (: ,2))\n\n    function testsimilar(args...)\n        try\n           similar(args...)\n        catch e\n            @test e isa MethodError\n            io = IOBuffer()\n            showerror(io, e)\n            s = split(String(take!(io)),'\\n')[1]\n            @test occursin(repr(similar), s)\n        end\n    end\n\n    testsimilar(typeof(A), (:, :))\n    testsimilar(typeof(A), (:, 2))\n    testsimilar(typeof(A), (:, 1:3))\n\n    @testset \"similar with OffsetArray type (issue #263)\" begin\n        for i in Any[[1,2,3], 1:3, SVector{2,Int}(1,2), reshape(1:4, 2, 2)]\n            k = OffsetArray(i, map(x -> -2, size(i)))\n            j = similar(typeof(k), axes(k))\n            @test axes(j) == axes(k)\n            @test eltype(j) == eltype(k)\n            j = similar(typeof(k), size(k))\n            @test eltype(j) == eltype(k)\n            @test size(j) == size(k)\n            @test all(==(1), first.(axes(j)))\n        end\n    end\nend\n\n# custom FillArray with BigInt axes, used to test `reshape`\nstruct MyBigFill{T,N} <: AbstractArray{T,N}\n    val :: T\n    axes :: NTuple{N,Base.OneTo{BigInt}}\nend\nMyBigFill(val, sz::Tuple{}) = MyBigFill{typeof(val),0}(val, sz)\nMyBigFill(val, sz::NTuple{N,BigInt}) where {N} = MyBigFill(val, map(Base.OneTo, sz))\nMyBigFill(val, sz::Tuple{Vararg{Integer}}) = MyBigFill(val, map(BigInt, sz))\nBase.size(M::MyBigFill) = map(length, M.axes)\nBase.axes(M::MyBigFill) = M.axes\nfunction Base.getindex(M::MyBigFill{<:Any,N}, ind::Vararg{Integer,N}) where {N}\n    checkbounds(M, ind...)\n    M.val\nend\nfunction Base.isassigned(M::MyBigFill{<:Any,N}, ind::Vararg{BigInt,N}) where {N}\n    checkbounds(M, ind...)\n    true\nend\nfunction Base.reshape(M::MyBigFill, ind::NTuple{N,BigInt}) where {N}\n    length(M) == prod(ind) || throw(ArgumentError(\"length mismatch in reshape\"))\n    MyBigFill(M.val, ind)\nend\nBase.reshape(M::MyBigFill, ind::Tuple{}) = MyBigFill(M.val, ind)\n\n@testset \"reshape\" begin\n    A0 = [1 3; 2 4]\n    A = OffsetArray(A0, (-1,2))\n\n    B = reshape(A0, -10:-9, 9:10)\n    @test isa(B, OffsetArray{Int,2})\n    @test parent(B) == A0\n    @test axes(B) == IdentityUnitRange.((-10:-9, 9:10))\n    B = reshape(A, -10:-9, 9:10)\n    @test isa(B, OffsetArray{Int,2})\n    @test pointer(parent(B)) === pointer(A0)\n    @test axes(B) == IdentityUnitRange.((-10:-9, 9:10))\n    b = reshape(A, -7:-4)\n    @test axes(b) == (IdentityUnitRange(-7:-4),)\n    @test isa(parent(b), Vector{Int})\n    @test pointer(parent(b)) === pointer(parent(A))\n    @test parent(b) == A0[:]\n    a = OffsetArray(rand(3,3,3), -1:1, 0:2, 3:5)\n    # Offset axes are required for reshape(::OffsetArray, ::Val) support\n    b = reshape(a, Val(2))\n    @test isa(b, OffsetArray{Float64,2})\n    @test pointer(parent(b)) === pointer(parent(a))\n    @test axes(b) == IdentityUnitRange.((-1:1, 1:9))\n    b = reshape(a, Val(4))\n    @test isa(b, OffsetArray{Float64,4})\n    @test pointer(parent(b)) === pointer(parent(a))\n    @test axes(b) == (axes(a)..., IdentityUnitRange(1:1))\n\n    @test reshape(OffsetArray(-1:0, -1:0), :, 1) == reshape(-1:0, 2, 1)\n    @test reshape(OffsetArray(-1:2, -1:2), -2:-1, :) == reshape(-1:2, -2:-1, 2)\n\n    @test reshape(OffsetArray(-1:0, -1:0), :) == OffsetArray(-1:0, -1:0)\n    @test reshape(A, :) == reshape(A0, :)\n\n    # reshape with one Colon for AbstractArrays\n    B = reshape(A0, -10:-9, :)\n    @test B isa OffsetArray{Int,2}\n    @test parent(B) == A0\n    @test no_offset_axes(B, 1) == -10:-9\n    @test axes(B, 2) == axes(A0, 2)\n\n    B = reshape(A0, -10:-9, 3:3, :)\n    @test B isa OffsetArray{Int,3}\n    @test same_value(A0, B)\n    @test no_offset_axes(B, 1) == -10:-9\n    @test no_offset_axes(B, 2) == 3:3\n    @test axes(B, 3) == 1:2\n\n    B = reshape(A0, -10:-9, 3:4, :)\n    @test B isa OffsetArray{Int,3}\n    @test same_value(A0, B)\n    @test no_offset_axes(B, 1) == -10:-9\n    @test no_offset_axes(B, 2) == 3:4\n    @test axes(B, 3) == 1:1\n\n    # pop the parent\n    B = reshape(A, size(A))\n    @test B == A0\n    B = reshape(A, (Base.OneTo(2), 2))\n    @test B == A0\n    B = reshape(A, (2,:))\n    @test B == A0\n\n    # julialang/julia #33614\n    A = OffsetArray(-1:0, (-2,))\n    @test reshape(A, :) == A\n    Arsc = reshape(A, :, 1)\n    Arss = reshape(A, 2, 1)\n    @test Arsc[1,1] == Arss[1,1] == -1\n    @test Arsc[2,1] == Arss[2,1] == 0\n    @test_throws BoundsError Arsc[0,1]\n    @test_throws BoundsError Arss[0,1]\n    A = OffsetArray([-1,0], (-2,))\n    Arsc = reshape(A, :, 1)\n    Arsc[1,1] = 5\n    @test first(A) == 5\n\n    @testset \"issue #235\" begin\n        Vec64  = zeros(6)\n        ind_a_64 = 3\n        ind_a_32 =Int32.(ind_a_64)\n        @test reshape(Vec64, ind_a_32, :) == reshape(Vec64, ind_a_64, :)\n    end\n\n    R = reshape(zeros(6), 2, :)\n    @test R isa Matrix\n    @test axes(R) == (1:2, 1:3)\n    R = reshape(zeros(6,1), 2, :)\n    @test R isa Matrix\n    @test axes(R) == (1:2, 1:3)\n\n    R = reshape(zeros(6), 1:2, :)\n    @test axes(R) == (1:2, 1:3)\n    R = reshape(zeros(6,1), 1:2, :)\n    @test axes(R) == (1:2, 1:3)\n\n    r = OffsetArray(ZeroBasedRange(3:4), 1);\n    @test reshape(r, 2) == reshape(r, big(2)) == 3:4\n    @test reshape(r, (2,)) == reshape(r, (big(2),)) == 3:4\n    @test reshape(r, :) == 3:4\n    @test reshape(r, (:,)) == 3:4\n    @test reshape(r, big(2), 1) == reshape(3:4, 2, 1)\n\n    # getindex for a reshaped array that wraps an offset array is broken on 1.0\n    if VERSION >= v\"1.1\"\n        @test reshape(r, (2,:,4:4)) == OffsetArray(reshape(3:4, 2, 1, 1), 1:2, 1:1, 4:4)\n    end\n\n    # reshape works even if the parent doesn't have 1-based indices\n    # this works even if the parent doesn't support the reshape\n    r = OffsetArray(IdentityUnitRange(0:1), -1)\n    @test reshape(r, 2) == 0:1\n    @test reshape(r, (2,)) == 0:1\n    @test reshape(r, :) == OffsetArray(0:1, -1:0)\n    @test reshape(r, (:,)) == OffsetArray(0:1, -1:0)\n\n    @test reshape(ones(2:3, 4:5), (2, :)) == ones(2,2)\n\n    # more than one colon is not allowed\n    @test_throws Exception reshape(ones(3:4, 4:5, 1:2), :, :, 2)\n    @test_throws Exception reshape(ones(3:4, 4:5, 1:2), :, 2, :)\n\n    A = OffsetArray(rand(4, 4), -1, -1);\n    B = reshape(A, (2, :))\n    @test axes(B, 1) == 1:2\n    @test axes(B, 2) == 1:8\n\n    # some more exotic vector types\n    r = OffsetVector(CustomRange(ZeroBasedRange(0:2)), -2)\n    r2 = reshape(r, :)\n    @test r2 == r\n    r2 = reshape(r, 3)\n    @test axes(r2, 1) == 1:3\n    @test r2 == no_offset_view(r)\n    @test_throws Exception reshape(r, length(r) + 1)\n    @test_throws Exception reshape(r, 1:length(r) + 1)\n    rp = parent(r)\n    @test no_offset_axes(reshape(rp, 4:6), 1) == 4:6\n    @test axes(reshape(r, (3,1))) == (1:3, 1:1)\n\n    # reshape with one single colon becomes a `vec`\n    A = OffsetArray(rand(4, 4), -1, -1)\n    @test reshape(A, (:, )) == vec(A)\n    @test reshape(A, :) == vec(A)\n\n    # ensure that there's no ambiguity using AbstractArray and Tuple{Vararg{OffsetAxis}}\n    @test reshape(Fill(0), ()) === Fill(0)\n    # This test is broken currently on julia v\"1.12.0-DEV.780\"\n    @test try\n        reshape(Fill(2,6), big(2), :) == Fill(2, 2, 3)\n    catch e\n        e isa TypeError || rethrow()\n    end\n    @testset \"Tuple{Vararg{Integer}}\" begin\n        M = MyBigFill(4, (2, 3))\n        O = OffsetArray(M)\n        @test vec(O) isa MyBigFill\n        @test vec(O) == vec(M)\n\n        M = MyBigFill(4, (1,1))\n        O = OffsetArray(M)\n        @test reshape(O) == reshape(M)\n        @test reshape(O) isa MyBigFill\n    end\nend\n\n@testset \"permutedims\" begin\n    a = OffsetArray(1:2, 2:3)\n    @test permutedims(a) == reshape(1:2, 1, 2:3)\n    a = OffsetArray([10,11], Base.OneTo(2))\n    @test permutedims(a) == reshape(10:11, 1, 1:2)\n    a = OffsetArray(SVector{2}(1,2), 3:4)\n    @test permutedims(a) == reshape(1:2, 1, 3:4)\n\n    # check that the 2D case is unaffected\n    a = OffsetArray(reshape(1:2, 1, 2), 2:2, 4:5)\n    b = permutedims(a)\n    @test a[2,:] == b[:,2]\nend\n\n@testset \"Indexing with OffsetArray axes\" begin\n    A0 = [1 3; 2 4]\n\n    i1 = OffsetArray([2,1], (-5,))\n    i1 = OffsetArray([2,1], -5)\n    b = A0[i1, 1]\n    @test axes(b) == (IdentityUnitRange(-4:-3),)\n    @test b[-4] == 2\n    @test b[-3] == 1\n    b = A0[1,i1]\n    @test axes(b) == (IdentityUnitRange(-4:-3),)\n    @test b[-4] == 3\n    @test b[-3] == 1\n    v = view(A0, i1, 1)\n    @test axes(v) == (IdentityUnitRange(-4:-3),)\n    v = view(A0, 1:1, i1)\n    @test axes(v) == (Base.OneTo(1), IdentityUnitRange(-4:-3))\n\n    for r in (1:10, 1:1:10, StepRangeLen(1, 1, 10), LinRange(1, 10, 10), 0.1:0.2:0.9)\n        for s in (IdentityUnitRange(2:3), OffsetArray(2:3, 2:3))\n            @test axes(r[s]) == axes(s)\n        end\n    end\nend\n\n@testset \"logical indexing\" begin\n    A0 = [1 3; 2 4]\n    A = OffsetArray(A0, (-1,2))\n\n    @test A[A .> 2] == [3,4]\nend\n\n@testset \"copyto!\" begin\n    a = OffsetArray{Int}(undef, (-3:-1,))\n    fill!(a, -1)\n    copyto!(a, (1,2))   # non-array iterables\n    @test a[-3] == 1\n    @test a[-2] == 2\n    @test a[-1] == -1\n    fill!(a, -1)\n    copyto!(a, -2, (1,2))\n    @test a[-3] == -1\n    @test a[-2] == 1\n    @test a[-1] == 2\n    @test_throws BoundsError copyto!(a, 1, (1,2))\n    fill!(a, -1)\n    copyto!(a, -2, (1,2,3), 2)\n    @test a[-3] == -1\n    @test a[-2] == 2\n    @test a[-1] == 3\n    @test_throws BoundsError copyto!(a, -2, (1,2,3), 1)\n    fill!(a, -1)\n    copyto!(a, -2, (1,2,3), 1, 2)\n    @test a[-3] == -1\n    @test a[-2] == 1\n    @test a[-1] == 2\n\n    b = 1:2    # copy between AbstractArrays\n    bo = OffsetArray(1:2, (-3,))\n    if VERSION < v\"1.5-\"\n        @test_throws BoundsError copyto!(a, b)\n        fill!(a, -1)\n        copyto!(a, bo)\n        @test a[-3] == -1\n        @test a[-2] == 1\n        @test a[-1] == 2\n    else\n        # the behavior of copyto! is corrected as the documentation says \"first n element\"\n        # https://github.com/JuliaLang/julia/pull/34049\n        fill!(a, -1)\n        copyto!(a, bo)\n        @test a[-3] == 1\n        @test a[-2] == 2\n        @test a[-1] == -1\n    end\n    fill!(a, -1)\n    copyto!(a, -2, bo)\n    @test a[-3] == -1\n    @test a[-2] == 1\n    @test a[-1] == 2\n    @test_throws BoundsError copyto!(a, -4, bo)\n    @test_throws BoundsError copyto!(a, -1, bo)\n    fill!(a, -1)\n    copyto!(a, -3, b, 2)\n    @test a[-3] == 2\n    @test a[-2] == a[-1] == -1\n    @test_throws BoundsError copyto!(a, -3, b, 1, 4)\n    am = OffsetArray{Int}(undef, (1:1, 7:9))  # for testing linear indexing\n    fill!(am, -1)\n    copyto!(am, b)\n    @test am[1] == 1\n    @test am[2] == 2\n    @test am[3] == -1\n    @test am[1,7] == 1\n    @test am[1,8] == 2\n    @test am[1,9] == -1\nend\n\n@testset \"map\" begin\n    am = OffsetArray{Int}(undef, (1:1, 7:9))  # for testing linear indexing\n    fill!(am, -1)\n    copyto!(am, 1:2)\n\n    dest = similar(am)\n    map!(+, dest, am, am)\n    @test dest[1,7] == 2\n    @test dest[1,8] == 4\n    @test dest[1,9] == -2\n\n    @testset \"eltype conversion\" begin\n        a = OffsetArray(1:2, 1)\n        b = map(BigInt, a)\n        @test eltype(b) == BigInt\n        @test b == a\n        @test parent(b) isa AbstractRange\n\n        for ri in Any[2:3, Base.OneTo(2)]\n            for r in Any[IdentityUnitRange(ri), IdOffsetRange(ri), IdOffsetRange(ri, 1), OffsetArray(ri), OffsetArray(ri, 2)]\n                for T in [Int8, Int16, Int32, Int64, Int128, BigInt, Float32, Float64, BigFloat]\n                    r2 = map(T, r)\n                    @test eltype(r2) == T\n                    @test axes(r2) == axes(r)\n                    @test all(((x,y),) -> isequal(x,y), zip(r, r2))\n                end\n            end\n        end\n\n        @testset \"Bool\" begin\n            for ri in Any[0:0, 0:1, 1:0, 1:1, Base.OneTo(0), Base.OneTo(1)]\n                for r = Any[IdentityUnitRange(ri), IdOffsetRange(ri), IdOffsetRange(ri .- 1, 1), OffsetVector(ri)]\n                    r2 = map(Bool, r)\n                    @test eltype(r2) == Bool\n                    @test axes(r2) == axes(r)\n                    @test all(((x,y),) -> isequal(x,y), zip(r, r2))\n                end\n            end\n        end\n    end\nend\n\n@testset \"reductions\" begin\n    A = OffsetArray(rand(Int,4,4), (-3,5))\n    @test maximum(A) == maximum(parent(A))\n    @test minimum(A) == minimum(parent(A))\n    @test extrema(A) == extrema(parent(A))\n    @test sum(A) == sum(parent(A))\n    @test sum(A, dims=1) == OffsetArray(sum(parent(A), dims=1), A.offsets)\n    @test sum(A, dims=2) == OffsetArray(sum(parent(A), dims=2), A.offsets)\n    @test sum(A, dims=(1,2)) == OffsetArray(sum(parent(A), dims=(1,2)), A.offsets)\n    @test sum(view(OffsetArray(reshape(1:27, 3, 3, 3), 0, 0, 0), :, :, 1:2), dims=(2,3)) == reshape([51,57,63], 3, 1, 1)\n    C = similar(A)\n    cumsum!(C, A, dims = 1)\n    @test parent(C) == cumsum(parent(A), dims = 1)\n    @test parent(cumsum(A, dims = 1)) == cumsum(parent(A), dims = 1)\n    cumsum!(C, A, dims = 2)\n    @test parent(C) == cumsum(parent(A), dims = 2)\n    R = similar(A, (1:1, 6:9))\n    maximum!(R, A)\n    @test parent(R) == maximum(parent(A), dims = 1)\n    R = similar(A, (-2:1, 1:1))\n    maximum!(R, A)\n    @test parent(R) == maximum(parent(A), dims = 2)\n    amin, iamin = findmin(A)\n    pmin, ipmin = findmin(parent(A))\n    @test amin == pmin\n    @test A[iamin] == amin\n    @test amin == parent(A)[ipmin]\n    amax, iamax = findmax(A)\n    pmax, ipmax = findmax(parent(A))\n    @test amax == pmax\n    @test A[iamax] == amax\n    @test amax == parent(A)[ipmax]\n\n    amin, amax = extrema(parent(A))\n    @test clamp.(A, (amax+amin)/2, amax) == OffsetArray(clamp.(parent(A), (amax+amin)/2, amax), axes(A))\n\n    @testset \"mapreduce for OffsetRange\" begin\n        rangelist = Any[\n            # AbstractUnitRanges\n            5:100, UnitRange(5.0, 20.0), false:true,\n            IdOffsetRange(4:5),\n            IdentityUnitRange(4:5),\n            IdOffsetRange(1:10, 4),\n            # AbstractRanges\n            2:4:14, 1.5:1.0:10.5,\n            ]\n\n        for r in rangelist\n\n            a = OffsetVector(r, 2);\n            @test mapreduce(identity, +, a) == mapreduce(identity, +, r)\n            @test mapreduce(x -> x^2, (x,y) -> x, a) == mapreduce(x -> x^2, (x,y) -> x, r)\n\n            b = mapreduce(identity, +, a, dims = 1)\n            br = mapreduce(identity, +, r, dims = 1)\n            @test no_offset_view(b) == no_offset_view(br)\n            @test no_offset_axes(b, 1) == first(axes(a,1)):first(axes(a,1))\n\n            @test mapreduce(identity, +, a, init = 3) == mapreduce(identity, +, r, init = 3)\n            if VERSION >= v\"1.2\"\n                @test mapreduce((x,y) -> x*y, +, a, a) == mapreduce((x,y) -> x*y, +, r, r)\n                @test mapreduce((x,y) -> x*y, +, a, a, init = 10) == mapreduce((x,y) -> x*y, +, r, r, init = 10)\n            end\n\n            for f in [sum, minimum, maximum]\n                @test f(a) == f(r)\n\n                b = f(a, dims = 1);\n                br = f(r, dims = 1)\n                @test no_offset_view(b) == no_offset_view(br)\n                @test no_offset_axes(b, 1) == first(axes(a,1)):first(axes(a,1))\n\n                b = f(a, dims = 2);\n                br = f(r, dims = 2)\n                @test no_offset_view(b) == no_offset_view(br)\n                @test axes(b, 1) == axes(a,1)\n            end\n\n            @test extrema(a) == extrema(r)\n        end\n    end\nend\n\n# v  = OffsetArray([1,1e100,1,-1e100], (-3,))*1000\n# v2 = OffsetArray([1,-1e100,1,1e100], (5,))*1000\n# @test isa(v, OffsetArray)\n# cv  = OffsetArray([1,1e100,1e100,2], (-3,))*1000\n# cv2 = OffsetArray([1,-1e100,-1e100,2], (5,))*1000\n# @test isequal(cumsum_kbn(v), cv)\n# @test isequal(cumsum_kbn(v2), cv2)\n# @test isequal(sum_kbn(v), sum_kbn(parent(v)))\n\n@testset \"Collections\" begin\n    A = OffsetArray(rand(4,4), (-3,5))\n\n    @test unique(A, dims=1) == OffsetArray(parent(A), 0, first(axes(A, 2)) - 1)\n    @test unique(A, dims=2) == OffsetArray(parent(A), first(axes(A, 1)) - 1, 0)\n    v = OffsetArray(rand(8), (-2,))\n    @test sort(v) == OffsetArray(sort(parent(v)), v.offsets)\n    @test sortslices(A; dims=1) == OffsetArray(sortslices(parent(A); dims=1), A.offsets)\n    @test sortslices(A; dims=2) == OffsetArray(sortslices(parent(A); dims=2), A.offsets)\n    @test sort(A, dims = 1) == OffsetArray(sort(parent(A), dims = 1), A.offsets)\n    @test sort(A, dims = 2) == OffsetArray(sort(parent(A), dims = 2), A.offsets)\n\n    @test mapslices(sort, A, dims = 1) == OffsetArray(mapslices(sort, parent(A), dims = 1), A.offsets)\n    @test mapslices(sort, A, dims = 2) == OffsetArray(mapslices(sort, parent(A), dims = 2), A.offsets)\nend\n\n@testset \"rot/reverse\" begin\n    A = OffsetArray(rand(4,4), (-3,5))\n\n    @test rotl90(A) == OffsetArray(rotl90(parent(A)), A.offsets[[2,1]])\n    @test rotr90(A) == OffsetArray(rotr90(parent(A)), A.offsets[[2,1]])\n    @test reverse(A, dims = 1) == OffsetArray(reverse(parent(A), dims = 1), A.offsets)\n    @test reverse(A, dims = 2) == OffsetArray(reverse(parent(A), dims = 2), A.offsets)\nend\n\n@testset \"fill\" begin\n    B = fill(5, 1:3, -1:1)\n    @test no_offset_axes(B) == (1:3,-1:1)\n    @test all(B.==5)\n\n    B = fill(5, (1:3, -1:1))\n    @test no_offset_axes(B) == (1:3,-1:1)\n    @test all(B.==5)\n\n    B = fill(5, 3, -1:1)\n    @test no_offset_axes(B) == (1:3,-1:1)\n    @test all(B.==5)\n\n    @testset \"fill!\" begin\n        D = dzeros((2,2))\n        DO = OffsetArray(D, 2, 2)\n        fill!(DO, 1)\n        @test all(isequal(1), DO)\n        @test all(iszero, zero(DO))\n\n        S = SVector{2,Int}(1,1)\n        SO = OffsetVector(S, -1)\n        @test zero(SO) isa typeof(SO)\n    end\nend\n\n@testset \"broadcasting\" begin\n    A = OffsetArray(rand(4,4), (-3,5))\n\n    @test A.+1 == OffsetArray(parent(A).+1, A.offsets)\n    @test 2*A == OffsetArray(2*parent(A), A.offsets)\n    @test A+A == OffsetArray(parent(A)+parent(A), A.offsets)\n    @test A.*A == OffsetArray(parent(A).*parent(A), A.offsets)\nend\n\n@testset \"@inbounds\" begin\n    a = OffsetArray(zeros(7), -3:3)\n    unsafe_fill!(x) = @inbounds(for i in axes(x,1); x[i] = i; end)\n    function unsafe_sum(x)\n        s = zero(eltype(x))\n        @inbounds for i in axes(x,1)\n            s += x[i]\n        end\n        s\n    end\n    unsafe_fill!(a)\n    for i = -3:3\n        @test a[i] == i\n    end\n    @test unsafe_sum(a) == 0\nend\n\n@testset \"Resizing OffsetVectors\" begin\n    local a = OffsetVector(rand(5),-3)\n    axes(a,1) == -2:2\n    length(a) == 5\n    resize!(a,3)\n    length(a) == 3\n    axes(a,1) == -2:0\n    @test_throws ArgumentError resize!(a,-3)\nend\n\n####\n#### type defined for testing no_offset_view\n####\n\nstruct NegativeArray{T,N,S <: AbstractArray{T,N}} <: AbstractArray{T,N}\n    parent::S\nend\n\n# Note: this defines the axes-of-the-axes to be OneTo.\n# In general this isn't recommended, because\n#    positionof(A, i, j, ...) == map(getindex, axes(A), (i, j, ...))\n# is quite desirable, and this requires that the axes be \"identity\" ranges, i.e.,\n# `r[i] == i`.\n# Nevertheless it's useful to test this on a \"broken\" implementation\n# to make sure we still get the right answer.\nBase.axes(A::NegativeArray) = map(n -> (-n):(-1), size(A.parent))\n\nBase.size(A::NegativeArray) = size(A.parent)\n\nfunction Base.getindex(A::NegativeArray{T,N}, I::Vararg{Int,N}) where {T,N}\n    getindex(A.parent, (I .+ size(A.parent) .+ 1)...)\nend\n\nstruct PointlessWrapper{T,N, A <: AbstractArray{T,N}} <: AbstractArray{T,N}\n    parent :: A\nend\nBase.parent(x::PointlessWrapper) = x.parent\nBase.size(x::PointlessWrapper) = size(parent(x))\nBase.axes(x::PointlessWrapper) = axes(parent(x))\nBase.getindex(x::PointlessWrapper, i...) = x.parent[i...]\n\n@testset \"no offset view\" begin\n    # OffsetArray fallback\n    A = randn(3, 3)\n    @inferred no_offset_view(A)\n    O1 = OffsetArray(A, -1:1, 0:2)\n    O2 = OffsetArray(O1, -2:0, -3:(-1))\n    @test no_offset_view(O2) ≡ A\n    @inferred no_offset_view(O1)\n    @inferred no_offset_view(O2)\n\n    P = PointlessWrapper(A)\n    @test @inferred(no_offset_view(P)) === P\n    @test @inferred(no_offset_view(A)) === A\n    a0 = reshape([1])\n    @test @inferred(no_offset_view(a0)) === a0\n    a0v = view(a0)\n    @test @inferred(no_offset_view(a0v)) === a0v\n\n    # generic fallback\n    A = collect(reshape(1:12, 3, 4))\n    N = NegativeArray(A)\n    @test N[-3, -4] == 1\n    V = no_offset_view(N)\n    @test collect(V) == A\n    A = reshape(view([5], 1, 1))\n    @test no_offset_view(A) == A\n\n    # bidirectional\n    B = BidirectionalVector([1, 2, 3])\n    pushfirst!(B, 0)\n    OB = OffsetArrays.no_offset_view(B)\n    @test no_offset_axes(OB, 1) == 1:4\n    @test collect(OB) == 0:3\n\n    # issue #198\n    offax = axes(OffsetVector(1:10, -5), 1)\n    noffax = OffsetArrays.no_offset_view(offax)\n    @test noffax == -4:5\n    @test axes(noffax, 1) == 1:10   # ideally covered by the above, but current it isn't\n    @test isa(noffax, AbstractUnitRange)\n\n    r = Base.OneTo(4)\n    @test OffsetArrays.no_offset_view(r) isa typeof(r)\n\n    # SubArrays\n    A = reshape(1:12, 3, 4)\n    V = view(A, OffsetArrays.IdentityUnitRange(2:3), OffsetArrays.IdentityUnitRange(2:3))\n    if collect(V) == [5 8; 6 9]   # julia 1.0 has a bug here\n        @test OffsetArrays.no_offset_view(V) == [5 8; 6 9]\n    end\n    V = view(A, OffsetArrays.IdentityUnitRange(2:3), 2)\n    @test V != [5;6]\n    if collect(V) == [5;6]\n        @test OffsetArrays.no_offset_view(V) == [5;6]\n    end\n    O = OffsetArray(A, -1:1, 0:3)\n    V = view(O, 0:1, 1:2)\n    @test V == OffsetArrays.no_offset_view(V) == [5 8; 6 9]\n    r1, r2 = OffsetArrays.IdOffsetRange(1:3, -2), OffsetArrays.IdentityUnitRange(2:3)\n    V = view(O, r1, r2)\n    @test V != collect(V)\n    @test OffsetArrays.no_offset_view(V) == collect(V)\n    V = @view O[:,:]\n    @test IndexStyle(A) == IndexStyle(O) == IndexStyle(V) == IndexStyle(OffsetArrays.no_offset_view(V)) == IndexLinear()\n\n    @testset \"issue #375\" begin\n        arr = OffsetArray(reshape(1:15, 3, 5), 2, 3)\n        arr_no_offset = OffsetArrays.no_offset_view(@view arr[:, 4])\n        @test all(!Base.has_offset_axes, axes(arr_no_offset))\n    end\nend\n\n@testset \"no nesting\" begin\n    A = randn(2, 3)\n    x = A[2, 2]\n    O1 = OffsetArray(A, -1:0, -1:1)\n    O2 = OffsetArray(O1, 0:1, 0:2)\n    @test parent(O1) ≡ parent(O2)\n    @test eltype(O1) ≡ eltype(O2)\n    O2[1, 1] = x + 1            # just a sanity check\n    @test A[2, 2] == x + 1\nend\n\n@testset \"mutating functions for OffsetVector\" begin\n    # push!\n    o = OffsetVector(Int[], -1)\n    @test push!(o) === o\n    @test no_offset_axes(o, 1) == 0:-1\n    @test push!(o, 1) === o\n    @test no_offset_axes(o, 1) == 0:0\n    @test o[end] == 1\n    @test push!(o, 2, 3) === o\n    @test no_offset_axes(o, 1) == 0:2\n    @test o[end-1:end] == [2, 3]\n    # pop!\n    o = OffsetVector([1, 2, 3], -1)\n    @test pop!(o) == 3\n    @test no_offset_axes(o, 1) == 0:1\n    # append!\n    o = OffsetVector([1, 2, 3], -1)\n    append!(o, [4, 5])\n    @test no_offset_axes(o, 1) == 0:4\n    # empty!\n    o = OffsetVector([1, 2, 3], -1)\n    @test empty!(o) === o\n    @test no_offset_axes(o, 1) == 0:-1\nend\n\n@testset \"searchsorted (#85)\" begin\n    o = OffsetVector([1,3,4,5],-2)\n    @test searchsortedfirst(o,-2) == -1\n    @test searchsortedfirst(o, 1) == -1\n    @test searchsortedfirst(o, 2) ==  0\n    @test searchsortedfirst(o, 5) ==  2\n    @test searchsortedfirst(o, 6) ==  3\n    @test searchsortedlast(o, -2) == -2\n    @test searchsortedlast(o,  1) == -1\n    @test searchsortedlast(o,  2) == -1\n    @test searchsortedlast(o,  5) ==  2\n    @test searchsortedlast(o,  6) ==  2\n    @test searchsorted(o, -2) == -1:-2\n    @test searchsorted(o,  1) == -1:-1\n    @test searchsorted(o,  2) ==  0:-1\n    @test searchsorted(o,  5) ==  2:2\n    @test searchsorted(o,  6) ==  3:2\n\n    if VERSION > v\"1.2\"\n        # OffsetVector of another offset vector\n        v = OffsetVector(Base.IdentityUnitRange(4:10),-2)\n        @test searchsortedfirst(v, first(v)-1) == firstindex(v)\n        for i in axes(v,1)\n            @test searchsortedfirst(v, v[i]) == i\n        end\n        @test searchsortedfirst(v, last(v)+1) == lastindex(v)+1\n        @test searchsortedlast(v, first(v)-1) == firstindex(v)-1\n        for i in axes(v,1)\n            @test searchsortedlast(v, v[i]) == i\n        end\n        @test searchsortedlast(v, last(v)+1) == lastindex(v)\n        @test searchsorted(v, first(v)-1) === firstindex(v) .+ (0:-1)\n        for i in axes(v,1)\n            @test searchsorted(v, v[i]) == i:i\n        end\n        @test searchsorted(v, last(v)+1) === lastindex(v) .+ (1:0)\n    end\n\n    v = OffsetVector{Float64, OffsetVector{Float64, Vector{Float64}}}(OffsetVector([2,2,3,3,3,4], 3), 4)\n    @test searchsortedfirst(v, minimum(v)-1) == firstindex(v)\n    for el in unique(v)\n        @test searchsortedfirst(v, el) == findfirst(isequal(el), v)\n    end\n    @test searchsortedfirst(v, maximum(v)+1) == lastindex(v)+1\n\n    @test searchsortedlast(v, minimum(v)-1) == firstindex(v)-1\n    for el in unique(v)\n        @test searchsortedlast(v, el) == findlast(isequal(el), v)\n    end\n    @test searchsortedlast(v, maximum(v)+1) == lastindex(v)\n\n    @test searchsorted(v, minimum(v)-1) === firstindex(v) .+ (0:-1)\n    for el in unique(v)\n        @test searchsorted(v, el) == findfirst(isequal(el), v):findlast(isequal(el), v)\n    end\n    @test searchsorted(v, maximum(v)+1) === lastindex(v) .+ (1:0)\n\n    soa = OffsetArray([2,2,3], typemax(Int)-3)\n    @test searchsortedfirst(soa, 1) == firstindex(soa) == typemax(Int)-2\n    @test searchsortedfirst(soa, 2) == firstindex(soa) == typemax(Int)-2\n    @test searchsortedfirst(soa, 3) == lastindex(soa) == typemax(Int)\n\n    soa = OffsetArray([2,2,3], typemin(Int))\n    @test searchsortedlast(soa, 2) == firstindex(soa) + 1 == typemin(Int) + 2\n    @test searchsortedlast(soa, 3) == lastindex(soa) == typemin(Int) + 3\n    @test searchsortedlast(soa, 1) == typemin(Int)\n\n    soa = OffsetArray([2,2,3], typemax(Int)-4)\n    @test searchsorted(soa, 1) === firstindex(soa) .+ (0:-1)\n    @test searchsorted(soa, 2) == firstindex(soa) .+ (0:1) == typemax(Int) .+ (-3:-2)\n    @test searchsorted(soa, 3) == lastindex(soa) .+ (0:0) == typemax(Int) .+ (-1:-1)\n    @test searchsorted(soa, 4) === lastindex(soa) .+ (1:0)\n\n    soa = OffsetArray([2,2,3], typemax(Int)-3)\n    @test searchsorted(soa, 1) === firstindex(soa) .+ (0:-1)\n    @test searchsorted(soa, 2) == firstindex(soa) .+ (0:1) == typemax(Int) .+ (-2:-1)\n    @test searchsorted(soa, 3) == lastindex(soa) .+ (0:0) == typemax(Int) .+ (0:0)\n    @test searchsorted(soa, 4) === lastindex(soa) .+ (1:0)\n\n    soa = OffsetArray([2,2,3], typemin(Int))\n    @test searchsorted(soa, 1) === firstindex(soa) .+ (0:-1)\n    @test searchsorted(soa, 2) == firstindex(soa) .+ (0:1) == typemin(Int) .+ (1:2)\n    @test searchsorted(soa, 3) == lastindex(soa) .+ (0:0) == typemin(Int) .+ (3:3)\n    @test searchsorted(soa, 4) === lastindex(soa) .+ (1:0)\nend\n\n@testset \"Adapt\" begin\n    # We need another storage type, CUDA.jl defines one but we can't use that for CI\n    # let's define an appropriate method for SArrays\n    Adapt.adapt_storage(::Type{SA}, xs::Array) where SA<:SArray         = convert(SA, xs)   # ambiguity\n    Adapt.adapt_storage(::Type{SA}, xs::AbstractArray) where SA<:SArray = convert(SA, xs)\n    arr = OffsetArray(rand(3, 3), -1:1, -1:1)\n    s_arr = adapt(SMatrix{3,3}, arr)\n    @test parent(s_arr) isa SArray\n    @test arr == adapt(Array, s_arr)\n\n    arr2 = OffsetArray(view(rand(5, 5), 2:4, 2:4), -1:1, -1:1)\n\n    if isdefined(Adapt, :parent_type)\n        @test Adapt.parent_type(typeof(arr)) == typeof(arr.parent)\n        @test Adapt.unwrap_type(typeof(arr)) == typeof(arr.parent)\n        @test Adapt.unwrap_type(typeof(arr2)) == typeof(arr.parent)\n    end\nend\n\n@testset \"Pointer\" begin\n    a = OffsetVector(collect(10:20), 9);\n    @test 12 == a[12] == unsafe_load(pointer(a), 12 + (1 - firstindex(a))) == unsafe_load(pointer(a, 12))\n\n    A = OffsetArray(reshape(collect(10:130), (11,11)), 9, 9);\n    @test 21 == A[12] == unsafe_load(pointer(A), 12) == unsafe_load(pointer(A, 12))\n    @test 61 == A[52] == unsafe_load(pointer(A), 52) == unsafe_load(pointer(A, 52))\n\n    @test pointer(a) === pointer(parent(a))\n    @test pointer(A) === pointer(parent(A))\n    @test pointer(a, 12) === pointer(parent(a), 12 + (1 - firstindex(a)))\n    @test pointer(A, 12) === pointer(parent(A), 12)\n    @test pointer(a) === pointer(a, firstindex(a))\n    @test pointer(A) === pointer(A, firstindex(A))\n    if VERSION ≥ v\"1.5\"\n        @test pointer(a') === pointer(parent(a))\n        @test pointer(A') === pointer(parent(A))\n        @test pointer(a', 5) === pointer(parent(a), 5)\n        @test pointer(A', 15) === pointer(parent(A)', 15)\n    end\n\n    @test Base.cconvert(Ptr{eltype(A)}, A) == Base.cconvert(Ptr{eltype(A)}, parent(A))\nend\n\n# issue 171\nstruct Foo2\n    o::OffsetArray{Float64,1,Array{Float64,1}}\nend\n\n@testset \"convert\" begin\n    d = Diagonal([1,1,1])\n    M = convert(Matrix{Float64}, d)\n    od = OffsetArray(d, 1, 1)\n    oM = convert(OffsetMatrix{Float64, Matrix{Float64}}, od)\n    @test eltype(oM) == Float64\n    @test typeof(parent(oM)) == Matrix{Float64}\n    @test oM == od\n    oM2 = convert(OffsetMatrix{Float64, Matrix{Float64}}, d)\n    @test eltype(oM2) == Float64\n    @test typeof(parent(oM2)) == Matrix{Float64}\n    @test oM2 == d\n\n    # issue 171\n    O = zeros(Int, 0:2)\n    F = Foo2(O)\n    @test F.o == O\n\n    a = [MMatrix{2,2}(1:4) for i = 1:2]\n    oa = [OffsetArray(ai, 0, 0) for ai in a]\n    b = ones(2,2)\n    @test b * a == b * oa\n\n    for a = [1:4, ones(1:5)]\n        for T in [OffsetArray, OffsetVector,\n            OffsetArray{eltype(a)}, OffsetArray{Float32},\n            OffsetVector{eltype(a)}, OffsetVector{Float32},\n            OffsetVector{Float32, Vector{Float32}},\n            OffsetVector{Float32, OffsetVector{Float32, Vector{Float32}}},\n            OffsetVector{eltype(a), typeof(a)},\n            ]\n\n            @test convert(T, a) isa T\n            @test convert(T, a) == a\n\n            b = T(a)\n            @test b isa T\n            @test b == a\n\n            b = T(a, 0)\n            @test b isa T\n            @test b == a\n\n            b = T(a, axes(a))\n            @test b isa T\n            @test b == a\n        end\n\n        a2 = reshape(a, :, 1)\n        for T in [OffsetArray{Float32}, OffsetMatrix{Float32}, OffsetArray{Float32, 2, Matrix{Float32}}]\n            b = T(a2, 0, 0)\n            @test b isa T\n            @test b == a2\n\n            b = T(a2, axes(a2))\n            @test b isa T\n            @test b == a2\n\n            b = T(a2, 1, 1)\n            @test no_offset_axes(b) == map((x,y) -> x .+ y, axes(a2), (1,1))\n\n            b = T(a2)\n            @test b isa T\n            @test b == a2\n        end\n        a3 = reshape(a, :, 1, 1)\n        for T in [OffsetArray{Float32}, OffsetArray{Float32, 3}, OffsetArray{Float32, 3, Array{Float32,3}}]\n            b = T(a3, 0, 0, 0)\n            @test b isa T\n            @test b == a3\n\n            b = T(a3, axes(a3))\n            @test b isa T\n            @test b == a3\n\n            b = T(a3, 1, 1, 1)\n            @test no_offset_axes(b) == map((x,y) -> x .+ y, axes(a3), (1,1,1))\n\n            b = T(a3)\n            @test b isa T\n            @test b == a3\n        end\n    end\n\n    a = ones(2:3)\n    b = convert(OffsetArray, a)\n    @test a === b\n    b = convert(OffsetVector, a)\n    @test a === b\n\n    # test that non-Int offsets work correctly\n    a = 1:4\n    b1 = OffsetVector{Float64,Vector{Float64}}(a, 2)\n    b2 = OffsetVector{Float64,Vector{Float64}}(a, big(2))\n    @test b1 == b2\n\n    a = ones(2:3)\n    b1 = OffsetArray{Float64, 1, typeof(a)}(a, (-1,))\n    b2 = OffsetArray{Float64, 1, typeof(a)}(a, (-big(1),))\n    @test b1 == b2\n\n    # test for custom offset arrays\n    a = ZeroBasedRange(1:3)\n    for T in [OffsetVector{Float64, UnitRange{Float64}}, OffsetVector{Int, Vector{Int}},\n        OffsetVector{Float64,OffsetVector{Float64,UnitRange{Float64}}},\n        OffsetArray{Int,1,OffsetArray{Int,1,UnitRange{Int}}},\n        ]\n\n        b = T(a)\n        @test b isa T\n        @test b == a\n\n        b = T(a, 2:4)\n        @test b isa T\n        @test no_offset_axes(b, 1) == 2:4\n        @test OffsetArrays.no_offset_view(b) == OffsetArrays.no_offset_view(a)\n\n        b = T(a, 1)\n        @test b isa T\n        @test axes(b, 1) == 1:3\n        @test OffsetArrays.no_offset_view(b) == OffsetArrays.no_offset_view(a)\n\n        c = convert(T, a)\n        @test c isa T\n        @test c == a\n    end\n\n    # test using custom indices\n    a = ones(2,2)\n    for T in [OffsetMatrix{Int}, OffsetMatrix{Float64}, OffsetMatrix{Float64, Matrix{Float64}},\n        OffsetMatrix{Int, Matrix{Int}}]\n\n        b = T(a, ZeroBasedIndexing())\n        @test b isa T\n        @test no_offset_axes(b) == (0:1, 0:1)\n    end\n\n    # changing the number of dimensions is not permitted\n    A = rand(2,2)\n    @test_throws MethodError convert(OffsetArray{Float64, 3}, A)\n    @test_throws MethodError convert(OffsetArray{Float64, 3, Array{Float64,3}}, A)\nend\n\n@testset \"center/centered\" begin\n    @testset \"center\" begin\n        A = reshape(collect(1:9), 3, 3)\n        c = OffsetArrays.center(A)\n        @test c == (2, 2)\n        @test A[c...] == 5\n        @test OffsetArrays.center(A, RoundDown) == OffsetArrays.center(A, RoundUp)\n\n        A = reshape(collect(1:6), 2, 3)\n        c = OffsetArrays.center(A)\n        @test OffsetArrays.center(A, RoundDown) == c\n        @test c == (1, 2)\n        @test A[c...] == 3\n        c = OffsetArrays.center(A, RoundUp)\n        @test c == (2, 2)\n        @test A[c...] == 4\n    end\n\n    @testset \"centered\" begin\n        A = reshape(collect(1:9), 3, 3)\n        Ao = OffsetArrays.centered(A)\n        @test OffsetArrays.centered(Ao) === Ao\n        @test OffsetArrays.centered(Ao, OffsetArrays.center(Ao)) === Ao\n        @test typeof(Ao) <: OffsetArray\n        @test parent(Ao) === A\n        @test Ao.offsets == (-2, -2)\n        @test Ao[0, 0] == 5\n\n        A = reshape(collect(1:6), 2, 3)\n        Ao = OffsetArrays.centered(A)\n        @test OffsetArrays.centered(A, OffsetArrays.center(A, RoundDown)) == Ao\n        @test typeof(Ao) <: OffsetArray\n        @test parent(Ao) === A\n        @test Ao.offsets == (-1, -2)\n        @test Ao[0, 0] == 3\n        Ao = OffsetArrays.centered(A, OffsetArrays.center(A, RoundUp))\n        @test typeof(Ao) <: OffsetArray\n        @test parent(Ao) === A\n        @test Ao.offsets == (-2, -2)\n        @test Ao[0, 0] == 4\n\n        A = reshape(collect(1:9), 3, 3)\n        Ao = OffsetArray(A, -1, -1)\n        Aoo = OffsetArrays.centered(Ao)\n        @test parent(Aoo) === A # there will be only one OffsetArray wrapper\n        @test Aoo.offsets == (-2, -2)\n        @test Aoo[0, 0] == 5\n\n        A = reshape(collect(1:9), 3, 3)\n        Aoo = OffsetArrays.centered(A, CartesianIndex(2,2))\n        c = (0,0)\n        i = CartesianIndex(c...)\n        @test Aoo[i] == Aoo[c...]\n\n    end\nend\n\n@testset \"Conversion to AbstractArray{T}\" begin\n    r = 1:4\n    T = Float64\n    V = typeof(map(T, r))\n    v = OffsetVector(r)\n    @test OffsetArray{T}(v) isa OffsetVector{T,V}\n    @test AbstractArray{T}(v) isa OffsetVector{T,V}\n    @test AbstractVector{T}(v) isa OffsetVector{T,V}\n    @test convert(AbstractVector{T}, v) isa OffsetVector{T,V}\n    @test convert(AbstractArray{T}, v) isa OffsetVector{T,V}\n    @test axes(OffsetArray{T}(v)) === axes(v)\n    @test axes(AbstractArray{T}(v)) === axes(v)\n    @test axes(AbstractVector{T}(v)) === axes(v)\n    @test axes(convert(AbstractVector{T}, v)) === axes(v)\n    @test axes(convert(AbstractArray{T}, v)) == axes(v)\n\n    A = SMatrix{2,2}(1, 0, 0, 1)\n    TA = typeof(map(T, A))\n    OA = OffsetMatrix(A, 3:4, 5:6)\n    @test OffsetArray{T}(OA) isa OffsetMatrix{T,TA}\n    @test AbstractArray{T}(OA) isa OffsetMatrix{T,TA}\n    @test AbstractMatrix{T}(OA) isa OffsetMatrix{T,TA}\n    @test convert(AbstractMatrix{T}, OA) isa OffsetMatrix{T,TA}\n    @test convert(AbstractArray{T}, OA) isa OffsetMatrix{T,TA}\n    @test axes(OffsetArray{T}(OA)) === axes(OA)\n    @test axes(AbstractArray{T}(OA)) === axes(OA)\n    @test axes(AbstractMatrix{T}(OA)) === axes(OA)\n    @test axes(convert(AbstractMatrix{T}, OA)) === axes(OA)\n    @test axes(convert(AbstractArray{T}, OA)) === axes(OA)\nend\n\n\ninclude(\"origin.jl\")\n\n@testset \"misc\" begin\n    @test OffsetArrays._subtractoffset(Base.OneTo(2), 1) isa AbstractUnitRange{Int}\n    @test OffsetArrays._subtractoffset(Base.OneTo(2), 1) == 0:1\n    @test OffsetArrays._subtractoffset(3:2:9, 1) isa AbstractRange{Int}\n    @test OffsetArrays._subtractoffset(3:2:9, 1) == 2:2:8\n\n    @test OffsetArrays._addoffset(Base.OneTo(2), 1) isa AbstractUnitRange{Int}\n    @test OffsetArrays._addoffset(Base.OneTo(2), 1) == 2:3\n    @test OffsetArrays._addoffset(3:2:9, 1) isa AbstractRange{Int}\n    @test OffsetArrays._addoffset(3:2:9, 1) == 4:2:10\nend\n\n@testset \"unsafe_wrap\" begin\n    p = Ptr{UInt16}(Libc.malloc(2*3*4*2))\n    @test unsafe_wrap(OffsetArray, p, 2, 3, 4) isa OffsetArray{UInt16, 3}\n    @test unsafe_wrap(OffsetArray, p, (2, 3, 4)) isa OffsetArray{UInt16, 3}\n    @test unsafe_wrap(OffsetVector, p, 2*3*4) isa OffsetVector{UInt16}\n    @test unsafe_wrap(OffsetMatrix, p, 2*3, 4) isa OffsetMatrix{UInt16}\n    @test unsafe_wrap(OffsetArray{UInt16}, p, 2, 3, 4) isa OffsetArray{UInt16, 3}\n    @test unsafe_wrap(OffsetArray{UInt16}, p, (2, 3, 4)) isa OffsetArray{UInt16, 3}\n    @test unsafe_wrap(OffsetVector{UInt16}, p, 2*3*4) isa OffsetVector{UInt16}\n    @test unsafe_wrap(OffsetMatrix{UInt16}, p, 2*3, 4) isa OffsetMatrix{UInt16}\n    p = Ptr{UInt8}(p)\n    @test unsafe_wrap(OffsetArray, p, 2:3, 3:5, 4:7) isa OffsetArray{UInt8, 3}\n    @test unsafe_wrap(OffsetArray, p, (2:3, 3:5, 4:7)) isa OffsetArray{UInt8, 3}\n    @test unsafe_wrap(OffsetVector, p, 1:(2*3*4) .- 1) isa OffsetVector{UInt8}\n    @test unsafe_wrap(OffsetMatrix, p, 1:(2*3) .+ 6, 4:7) isa OffsetMatrix{UInt8}\n    @test unsafe_wrap(OffsetMatrix, p, -5:5, Base.OneTo(3); own = true) isa OffsetMatrix{UInt8}\nend\n\n@info \"Following deprecations are expected\"\n@testset \"deprecations\" begin\n    A = reshape(collect(1:9), 3, 3)\n    @test OffsetArrays.centered(A, RoundDown) == OffsetArrays.centered(A, RoundUp)\nend\n"
  }
]