You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
ArrayInterface.axes docs, clean up, and ReinterpretArray support. (#222)
* +axis support methods from base and +tests
* Get rid of some no good very bad spaghetti code.
* Document examples of how to use axes here.
* Incorporate ReinterpretArray changes from ArrayInterface.axes for ReshapedReinterpretArray #210. Don't assume we can go to parent arrays anymore because there are too many assumptions (offsets, sizing, views, etc) that can change it.
* Document `SoneTo`
Copy file name to clipboardExpand all lines: docs/src/index.md
+68-2Lines changed: 68 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,7 +8,7 @@ Designs for new Base array interface primitives, used widely through scientific
8
8
9
9
## Inheriting Array Traits
10
10
11
-
Creating an array type with unique behavior in Julia is often accomplished by creating a lazy wrapper around previously defined array types.
11
+
Creating an array type with unique behavior in Julia is often accomplished by creating a lazy wrapper around previously defined array types (e.g. [composition by inheritance](https://en.wikipedia.org/wiki/Composition_over_inheritance)).
12
12
This allows the new array type to inherit functionality by redirecting methods to the parent array (e.g., `Base.size(x::Wrapper) = size(parent(x))`).
13
13
Generic design limits the need to define an excessive number of methods like this.
14
14
However, methods used to describe a type's traits often need to be explicitly defined for each trait method.
@@ -32,7 +32,7 @@ Most traits in `ArrayInterface` are a variant on this pattern.
32
32
33
33
## Static Traits
34
34
35
-
The size along one or more dimensions of an array may be known at compile time.
35
+
The size along one or more dimensions of an array may be known at compile time.
36
36
`ArrayInterface.known_size` is useful for extracting this information from array types and `ArrayInterface.size` is useful for extracting this information from an instance of an array.
37
37
For example:
38
38
@@ -94,6 +94,7 @@ If `x`'s first dimension is named `:dim_1` then calling `f(x, :dim_1)` would res
94
94
If users knew they always wanted to call `f(x, 2)` then they could define `h(x) = f(x, static(2))`, ensuring `f` passes along that information while compiling.
95
95
96
96
New types defining dimension names can do something similar to:
97
+
97
98
```julia
98
99
using Static
99
100
using ArrayInterface
@@ -107,4 +108,69 @@ Dimension names should be appropriately propagated between nested arrays using `
107
108
This allows types such as `SubArray` and `PermutedDimsArray` to work with named dimensions.
108
109
Similarly, other methods that return information corresponding to dimensions (e.g., `ArrayInterfce.size`, `ArrayInterface.axes`) use `to_parent_dims` to appropriately propagate parent information.
109
110
111
+
## Axes
112
+
113
+
Where Julia's currently documented [array interface](https://docs.julialang.org/en/v1/manual/interfaces/#man-interface-array) requires defining `Base.size`, ArrayInterface instead requires defining [`ArrayInterface.axes`](@ref) and [`ArrayInterface.axes_types`](@ref).
114
+
`ArrayInterface.axes_types(::Type{T})` facilitates propagation of a number of traits known at compile time (e.g., `known_size`, `known_offsets`) and `ArrayInterface.axes(::AbstractArray)` replaces `Base.OneTo` with `ArrayInterface.OptionallyStaticUnitRange` in situations where static information would otherwise be lost.
115
+
`ArrayInterface.axes(::AbstractArray, dim)` utilizes `to_dims`, [as described elsewhere](#dimensions).
116
+
117
+
### Simple Wrappers
118
+
119
+
Let's say we have a new array type doesn't affect axes then this is as simple as:
ArrayInterface.axes_types(::Type{T}) where {T<:SimpleWrapper} =axes_types(parent_type(T))
124
+
```
125
+
126
+
To reiterate, `ArrayInterface.axes` improves on `Base.axes` for few Base array types but is otherwise identical.
127
+
Therefore, the first method simply ensures you don't have to define multiple parametric methods for your new type to preserve statically sized nested axes (e.g., `SimpleWrapper{T,N,<:Transpose{T,<:AbstractVector}}`).
128
+
This is otherwise identical to standard inheritance by composition.
129
+
130
+
### When to Discard Axis Information
131
+
132
+
Occasionally the parent array's axis information can't be preserved.
133
+
For example, we can't map axis information from the parent array of `Base.ReshapedArray`.
134
+
In this case we can simply build axes from the new size information.
Defining these two methods ensures that other array types that wrap `OffsetArray` and appropriately define these methods propagate offsets independent of any dependency on `OffsetArray`.
174
+
It is entirely optional to define `ArrayInterface.size` for `OffsetArray` because the size can be derived from the axes.
175
+
However, in this particularly case we should also define
176
+
`ArrayInterface.size(A::OffsetArray) = ArrayInterface.size(parent(A))` because the relative offsets attached to `OffsetArray` do not change the size but may hide static sizes if using a relative offset that is defined with an `Int`.
0 commit comments