{"id":19093707,"url":"https://github.com/juliaarrays/offsetarrays.jl","last_synced_at":"2025-10-17T23:58:42.236Z","repository":{"id":13711998,"uuid":"16405992","full_name":"JuliaArrays/OffsetArrays.jl","owner":"JuliaArrays","description":"Fortran-like arrays with arbitrary, zero or negative starting indices.","archived":false,"fork":false,"pushed_at":"2024-04-17T07:46:44.000Z","size":1238,"stargazers_count":192,"open_issues_count":44,"forks_count":40,"subscribers_count":10,"default_branch":"master","last_synced_at":"2024-05-01T17:11:54.302Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Julia","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JuliaArrays.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-01-31T11:13:19.000Z","updated_at":"2024-05-21T05:45:35.722Z","dependencies_parsed_at":"2023-02-13T00:31:03.142Z","dependency_job_id":"62be58ae-f62f-47ca-b44d-0e7d14412c71","html_url":"https://github.com/JuliaArrays/OffsetArrays.jl","commit_stats":{"total_commits":325,"total_committers":37,"mean_commits":8.783783783783784,"dds":0.72,"last_synced_commit":"8e91956bf45dcac77033c5f4409b40d39c5b596f"},"previous_names":[],"tags_count":91,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JuliaArrays%2FOffsetArrays.jl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JuliaArrays%2FOffsetArrays.jl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JuliaArrays%2FOffsetArrays.jl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JuliaArrays%2FOffsetArrays.jl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JuliaArrays","download_url":"https://codeload.github.com/JuliaArrays/OffsetArrays.jl/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240142876,"owners_count":19754641,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-09T03:25:47.904Z","updated_at":"2025-10-17T23:58:37.201Z","avatar_url":"https://github.com/JuliaArrays.png","language":"Julia","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 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\u003e using OffsetArrays\n\njulia\u003e 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\u003e axes(A) # indices of a Matrix start from 1 along each axis\n(Base.OneTo(3), Base.OneTo(5))\n\njulia\u003e 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\u003e OA[-1, 0]\n1.0\n\njulia\u003e 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\u003e using OffsetArrays: Origin\n\njulia\u003e 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\u003e 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\u003e A = Float64.(reshape(1:16, 4, 4));\n\njulia\u003e AO = Origin(0)(A);\n\njulia\u003e using LinearAlgebra\n\njulia\u003e 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\u003e 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\u003e 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\u003e 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\u003c!-- badges --\u003e\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","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjuliaarrays%2Foffsetarrays.jl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjuliaarrays%2Foffsetarrays.jl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjuliaarrays%2Foffsetarrays.jl/lists"}