@@ -9,13 +9,13 @@ import Base: convert, similar, length, size, axes, IndexStyle,
9
9
RowVector(vector)
10
10
11
11
A lazy-view wrapper of an `AbstractVector`, which turns a length-`n` vector into a `1×n`
12
- shaped row vector and represents the transpose of a vector (the elements are also transposed
13
- recursively).
12
+ shaped row vector and represents the transpose of a vector (although unlike `transpose`,
13
+ the elements are *not* transposed recursively).
14
14
15
15
By convention, a vector can be multiplied by a matrix on its left (`A * v`) whereas a row
16
- vector can be multiplied by a matrix on its right (such that `transpose (v) * A = transpose (transpose(A) * v)`). It
16
+ vector can be multiplied by a matrix on its right (such that `RowVector (v) * A = RowVector (transpose(A) * v)`). It
17
17
differs from a `1×n`-sized matrix by the facts that its transpose returns a vector and the
18
- inner product `transpose (v1) * v2` returns a scalar, but will otherwise behave similarly.
18
+ inner product `RowVector (v1) * v2` returns a scalar, but will otherwise behave similarly.
19
19
"""
20
20
struct RowVector{T,V<: AbstractVector } <: AbstractMatrix{T}
21
21
vec:: V
29
29
@inline RowVector {T} (vec:: AbstractVector{T} ) where {T} = RowVector {T,typeof(vec)} (vec)
30
30
31
31
# Constructors that take a size and default to Array
32
- @inline RowVector {T} (n:: Int ) where {T} = RowVector {T} (Vector {T} (n))
32
+ @inline RowVector {T} (n:: Int ) where {T} = RowVector {T} (Vector {T} (undef, n))
33
33
@inline RowVector {T} (n1:: Int , n2:: Int ) where {T} = n1 == 1 ?
34
- RowVector {T} (Vector {T} (n2) ) :
34
+ RowVector {T} (n2 ) :
35
35
error (" RowVector expects 1×N size, got ($n1 ,$n2 )" )
36
- @inline RowVector {T} (n:: Tuple{Int} ) where {T} = RowVector {T} (Vector {T} ( n[1 ]) )
36
+ @inline RowVector {T} (n:: Tuple{Int} ) where {T} = RowVector {T} (n[1 ])
37
37
@inline RowVector {T} (n:: Tuple{Int,Int} ) where {T} = n[1 ] == 1 ?
38
- RowVector {T} (Vector {T} ( n[2 ]) ) :
38
+ RowVector {T} (n[2 ]) :
39
39
error (" RowVector expects 1×N size, got $n " )
40
40
41
41
# Conversion of underlying storage
@@ -44,7 +44,7 @@ convert(::Type{RowVector{T,V}}, rowvec::RowVector) where {T,V<:AbstractVector} =
44
44
45
45
# similar tries to maintain the RowVector wrapper and the parent type
46
46
@inline similar (rowvec:: RowVector ) = RowVector (similar (parent (rowvec)))
47
- @inline similar (rowvec:: RowVector , :: Type{T} ) where {T} = RowVector (similar (parent (rowvec), transpose_type (T) ))
47
+ @inline similar (rowvec:: RowVector , :: Type{T} ) where {T} = RowVector (similar (parent (rowvec), T ))
48
48
49
49
# Resizing similar currently loses its RowVector property.
50
50
@inline similar (rowvec:: RowVector , :: Type{T} , dims:: Dims{N} ) where {T,N} = similar (parent (rowvec), T, dims)
@@ -54,40 +54,17 @@ parent(rowvec::RowVector) = rowvec.vec
54
54
# AbstractArray interface
55
55
@inline length (rowvec:: RowVector ) = length (rowvec. vec)
56
56
@inline size (rowvec:: RowVector ) = (1 , length (rowvec. vec))
57
- @inline size (rowvec:: RowVector , d) = ifelse (d== 2 , length (rowvec. vec), 1 )
58
- @inline axes (rowvec:: RowVector ) = (Base. OneTo (1 ), axes (rowvec. vec)[1 ])
59
- @inline axes (rowvec:: RowVector , d) = ifelse (d == 2 , axes (rowvec. vec)[1 ], Base. OneTo (1 ))
57
+ @inline axes (rowvec:: RowVector ) = (Base. OneTo (1 ), axes (rowvec. vec, 1 ))
60
58
IndexStyle (:: RowVector ) = IndexLinear ()
61
59
IndexStyle (:: Type{<:RowVector} ) = IndexLinear ()
62
60
63
-
64
- @propagate_inbounds getindex (rowvec:: RowVector , i) = rowvec. vec[i]
65
- @propagate_inbounds setindex! (rowvec:: RowVector , v, i) = setindex! (rowvec. vec, v, i)
66
-
67
- # Cartesian indexing is distorted by getindex
68
- # Furthermore, Cartesian indexes don't have to match shape, apparently!
69
- @inline function getindex (rowvec:: RowVector , i:: CartesianIndex )
70
- @boundscheck if ! (i. I[1 ] == 1 && i. I[2 ] ∈ axes (rowvec. vec)[1 ] && check_tail_indices (i. I... ))
71
- throw (BoundsError (rowvec, i. I))
72
- end
73
- @inbounds return rowvec. vec[i. I[2 ]]
74
- end
75
- @inline function setindex! (rowvec:: RowVector , v, i:: CartesianIndex )
76
- @boundscheck if ! (i. I[1 ] == 1 && i. I[2 ] ∈ axes (rowvec. vec)[1 ] && check_tail_indices (i. I... ))
77
- throw (BoundsError (rowvec, i. I))
78
- end
79
- @inbounds rowvec. vec[i. I[2 ]] = v
80
- end
81
-
82
- @propagate_inbounds getindex (rowvec:: RowVector , :: CartesianIndex{0} ) = getindex (rowvec)
83
- @propagate_inbounds getindex (rowvec:: RowVector , i:: CartesianIndex{1} ) = getindex (rowvec, i. I[1 ])
84
-
85
- @propagate_inbounds setindex! (rowvec:: RowVector , v, :: CartesianIndex{0} ) = setindex! (rowvec, v)
86
- @propagate_inbounds setindex! (rowvec:: RowVector , v, i:: CartesianIndex{1} ) = setindex! (rowvec, v, i. I[1 ])
61
+ @propagate_inbounds getindex (rowvec:: RowVector , i:: Int ) = rowvec. vec[i]
62
+ @propagate_inbounds setindex! (rowvec:: RowVector , v, i:: Int ) = setindex! (rowvec. vec, v, i)
87
63
88
64
# helper function for below
89
- @inline to_vec (rowvec:: RowVector ) = rowvec. vec
90
-
65
+ to_vec (r:: RowVector ) = parent (r)
66
+ to_vec (x) = x
67
+ @inline to_vecs (rowvecs... ) = map (to_vec, rowvecs)
91
68
# map: Preserve the RowVector by un-wrapping and re-wrapping, but note that `f`
92
69
# expects to operate within the transposed domain, so to_vec transposes the elements
93
70
@inline map (f, rowvecs:: RowVector... ) = RowVector (map (f, to_vecs (rowvecs... )... ))
98
75
99
76
# Horizontal concatenation #
100
77
101
- @inline hcat (X:: RowVector... ) = RowVector (vcat (X ... ))
102
- @inline hcat (X:: Union{RowVector,Number} ...) = RowVector (vcat (X ... ))
78
+ @inline hcat (X:: RowVector... ) = RowVector (mapreduce (parent, vcat, X ))
79
+ @inline hcat (X:: Union{RowVector,Number} ...) = RowVector (mapreduce (to_vec, vcat, X ))
103
80
104
81
@inline typed_hcat (:: Type{T} , X:: RowVector... ) where {T} =
105
- RowVector (typed_vcat (T, X ... ))
82
+ RowVector (Base . typed_vcat (T, to_vecs (X ... ) ... ))
106
83
@inline typed_hcat (:: Type{T} , X:: Union{RowVector,Number} ...) where {T} =
107
- RowVector (typed_vcat (T, X ... ))
84
+ RowVector (Base . typed_vcat (T, to_vecs (X ... ) ... ))
108
85
109
86
# Multiplication #
110
87
116
93
if length (rowvec) != length (vec)
117
94
throw (DimensionMismatch (" A has dimensions $(size (rowvec)) but B has dimensions $(size (vec)) " ))
118
95
end
119
- sum (@inbounds (rowvec[i]* vec[i]) for i = 1 : length ( vec))
96
+ sum (@inbounds (rowvec[i]* vec[i]) for i in eachindex (rowvec, vec))
120
97
end
121
- @inline * (rowvec:: RowVector , mat:: AbstractMatrix ) = RowVector (transpose (transpose () mat) * rowvec. vec )
98
+ @inline * (rowvec:: RowVector , mat:: AbstractMatrix ) = RowVector (transpose (mat) * parent ( rowvec) )
122
99
* (:: RowVector , :: RowVector ) = throw (DimensionMismatch (" Cannot multiply two transposed vectors" ))
123
100
@inline * (vec:: AbstractVector , rowvec:: RowVector ) = vec .* rowvec
124
101
0 commit comments