@@ -1000,57 +1000,72 @@ create a `SubArray` view instead.
1000
1000
They can be used similarly to ` Array{Bool} ` arrays (which store one byte per boolean value),
1001
1001
and can be converted to/from the latter via ` Array(bitarray) ` and ` BitArray(array) ` , respectively.
1002
1002
1003
- A "strided" array is stored in memory with elements laid out in regular offsets such that
1004
- an instance with a supported ` isbits ` element type can be passed to
1005
- external C and Fortran functions that expect this memory layout. Strided arrays
1006
- must define a [ ` strides(A) ` ] ( @ref ) method that returns a tuple of "strides" for each dimension; a
1007
- provided [ ` stride(A,k) ` ] ( @ref ) method accesses the ` k ` th element within this tuple. Increasing the
1008
- index of dimension ` k ` by ` 1 ` should increase the index ` i ` of [ ` getindex(A,i) ` ] ( @ref ) by
1009
- [ ` stride(A,k) ` ] ( @ref ) . If a pointer conversion method [ ` Base.unsafe_convert(Ptr{T}, A) ` ] ( @ref ) is
1010
- provided, the memory layout must correspond in the same way to these strides. ` DenseArray ` is a
1011
- very specific example of a strided array where the elements are arranged contiguously, thus it
1012
- provides its subtypes with the appropriate definition of ` strides ` . More concrete examples
1013
- can be found within the [ interface guide for strided arrays] (@ref man-interface-strided-arrays).
1014
- [ ` StridedVector ` ] ( @ref ) and [ ` StridedMatrix ` ] ( @ref ) are convenient aliases for many of the builtin array types that
1015
- are considered strided arrays, allowing them to dispatch to select specialized implementations that
1016
- call highly tuned and optimized BLAS and LAPACK functions using just the pointer and strides.
1017
-
1018
- The following example computes the QR decomposition of a small section of a larger array, without
1019
- creating any temporaries, and by calling the appropriate LAPACK function with the right leading
1020
- dimension size and stride parameters.
1003
+ An array is "strided" if it is stored in memory with well-defined spacings (strides) between
1004
+ its elements. A strided array with a supported element type may be passed to an external
1005
+ (non-Julia) library like BLAS or LAPACK by simply passing its [ ` pointer ` ] ( @ref ) and the
1006
+ stride for each dimension. The [ ` stride(A, d) ` ] ( @ref ) is the distance between elements along
1007
+ dimension ` d ` . For example, the builtin ` Array ` returned by ` rand(5,7,2) ` has its elements
1008
+ arranged contiguously in column major order. This means that the stride of the first
1009
+ dimension — the spacing between elements in the same column — is ` 1 ` :
1021
1010
1022
1011
``` julia-repl
1023
- julia> a = rand(10, 10)
1024
- 10×10 Array{Float64,2}:
1025
- 0.517515 0.0348206 0.749042 0.0979679 … 0.75984 0.950481 0.579513
1026
- 0.901092 0.873479 0.134533 0.0697848 0.0586695 0.193254 0.726898
1027
- 0.976808 0.0901881 0.208332 0.920358 0.288535 0.705941 0.337137
1028
- 0.657127 0.0317896 0.772837 0.534457 0.0966037 0.700694 0.675999
1029
- 0.471777 0.144969 0.0718405 0.0827916 0.527233 0.173132 0.694304
1030
- 0.160872 0.455168 0.489254 0.827851 … 0.62226 0.0995456 0.946522
1031
- 0.291857 0.769492 0.68043 0.629461 0.727558 0.910796 0.834837
1032
- 0.775774 0.700731 0.700177 0.0126213 0.00822304 0.327502 0.955181
1033
- 0.9715 0.64354 0.848441 0.241474 0.591611 0.792573 0.194357
1034
- 0.646596 0.575456 0.0995212 0.038517 0.709233 0.477657 0.0507231
1035
-
1036
- julia> b = view(a, 2:2:8,2:2:4)
1037
- 4×2 view(::Array{Float64,2}, 2:2:8, 2:2:4) with eltype Float64:
1038
- 0.873479 0.0697848
1039
- 0.0317896 0.534457
1040
- 0.455168 0.827851
1041
- 0.700731 0.0126213
1042
-
1043
- julia> (q, r) = qr(b);
1044
-
1045
- julia> q
1046
- 4×4 LinearAlgebra.QRCompactWYQ{Float64,Array{Float64,2}}:
1047
- -0.722358 0.227524 -0.247784 -0.604181
1048
- -0.0262896 -0.575919 -0.804227 0.144377
1049
- -0.376419 -0.75072 0.540177 -0.0541979
1050
- -0.579497 0.230151 -0.00552346 0.781782
1051
-
1052
- julia> r
1053
- 2×2 Array{Float64,2}:
1054
- -1.20921 -0.383393
1055
- 0.0 -0.910506
1012
+ julia> A = rand(5,7,2);
1013
+
1014
+ julia> stride(A,1)
1015
+ 1
1016
+ ```
1017
+
1018
+ The stride of the second dimension is the spacing between elements in the same row, skipping
1019
+ as many elements as there are in a single column (` 5 ` ). Similarly, jumping between the two
1020
+ "pages" (in the third dimension) requires skipping ` 5*7 == 35 ` elements. The [ ` strides ` ] ( @ref )
1021
+ of this array is the tuple of these three numbers together:
1022
+
1023
+ ``` julia-repl
1024
+ julia> strides(A)
1025
+ (1, 5, 35)
1056
1026
```
1027
+
1028
+ In this particular case, the number of elements skipped _ in memory_ matches the number of
1029
+ _ linear indices_ skipped. This is only the case for contiguous arrays like ` Array ` (and
1030
+ other ` DenseArray ` subtypes) and is not true in general. Views with range indices are a good
1031
+ example of _ non-contiguous_ strided arrays; consider ` V = @view A[1:3:4, 2:2:6, 2:-1:1] ` .
1032
+ This view ` V ` refers to the same memory as ` A ` but is skipping and re-arranging some of its
1033
+ elements. The stride of the first dimension of ` V ` is ` 3 ` because we're only selecting every
1034
+ third row from our original array:
1035
+
1036
+ ``` julia-repl
1037
+ julia> V = @view A[1:3:4, 2:2:6, 2:-1:1];
1038
+
1039
+ julia> stride(V, 1)
1040
+ 3
1041
+ ```
1042
+
1043
+ This view is similarly selecting every other column from our original ` A ` — and thus it
1044
+ needs to skip the equivalent of two five-element columns when moving between indices in the
1045
+ second dimension:
1046
+
1047
+ ``` julia-repl
1048
+ julia> stride(V, 2)
1049
+ 10
1050
+ ```
1051
+
1052
+ The third dimension is interesting because its order is reversed! Thus to get from the first
1053
+ "page" to the second one it must go _ backwards_ in memory, and so its stride in this
1054
+ dimension is negative!
1055
+
1056
+ ``` julia-repl
1057
+ julia> stride(V, 3)
1058
+ -35
1059
+ ```
1060
+
1061
+ This means that the ` pointer ` for ` V ` is actually pointing into the middle of ` A ` 's memory
1062
+ block, and it refers to elements both backwards and forwards in memory. See the
1063
+ [ interface guide for strided arrays] (@ref man-interface-strided-arrays) for more details on
1064
+ defining your own strided arrays. [ ` StridedVector ` ] ( @ref ) and [ ` StridedMatrix ` ] ( @ref ) are
1065
+ convenient aliases for many of the builtin array types that are considered strided arrays,
1066
+ allowing them to dispatch to select specialized implementations that call highly tuned and
1067
+ optimized BLAS and LAPACK functions using just the pointer and strides.
1068
+
1069
+ It is worth emphasizing that strides are about offsets in memory rather than indexing. If
1070
+ you are looking to convert between linear (single-index) indexing and cartesian
1071
+ (multi-index) indexing, see [ ` LinearIndices ` ] ( @ref ) and [ ` CartesianIndices ` ] ( @ref ) .
0 commit comments