156 
156 

return x_vec, PermutedDimsArray_from_vec 
157 
157 

end 
158 
158 



159 
+ 
# Factorizations 

160 
+ 


161 
+ 
function to_vec(x::F) where {F <: SVD} 

162 
+ 
# Convert the vector S to a matrix so we can work with a vector of matrices 

163 
+ 
# only and inferrence work 

164 
+ 
v = [x.U, reshape(x.S, length(x.S), 1), x.Vt] 

165 
+ 
x_vec, back = to_vec(v) 

166 
+ 
function SVD_from_vec(v) 

167 
+ 
U, Smat, Vt = back(v) 

168 
+ 
return F(U, vec(Smat), Vt) 

169 
+ 
end 

170 
+ 
return x_vec, SVD_from_vec 

171 
+ 
end 

172 
+ 


173 
+ 
function to_vec(x::Cholesky) 

174 
+ 
x_vec, back = to_vec(x.factors) 

175 
+ 
function Cholesky_from_vec(v) 

176 
+ 
return Cholesky(back(v), x.uplo, x.info) 

177 
+ 
end 

178 
+ 
return x_vec, Cholesky_from_vec 

179 
+ 
end 

180 
+ 


181 
+ 
function to_vec(x::S) where {U, S <: Union{LinearAlgebra.QRCompactWYQ{U}, LinearAlgebra.QRCompactWY{U}}} 

182 
+ 
# x.T is composed of upper triangular blocks. The subdiagonals elements 

183 
+ 
# of the blocks are abitrary. We make sure to set all of them to zero 

184 
+ 
# to avoid NaN. 

185 
+ 
blocksize, cols = size(x.T) 

186 
+ 
T = zeros(U, blocksize, cols) 

187 
+ 


188 
+ 
for i in 0:div(cols  1, blocksize) 

189 
+ 
used_cols = i * blocksize 

190 
+ 
n = min(blocksize, cols  used_cols) 

191 
+ 
T[1:n, (1:n) .+ used_cols] = UpperTriangular(view(x.T, 1:n, (1:n) .+ used_cols)) 

192 
+ 
end 

193 
+ 


194 
+ 
x_vec, back = to_vec([x.factors, T]) 

195 
+ 


196 
+ 
function QRCompact_from_vec(v) 

197 
+ 
factors, Tback = back(v) 

198 
+ 
return S(factors, Tback) 

199 
+ 
end 

200 
+ 


201 
+ 
return x_vec, QRCompact_from_vec 

202 
+ 
end 

203 
+ 

159 
204 

# Nonarray data structures 
160 
205 


161 
206 

function to_vec(x::Tuple) 