Skip to content

Commit 7962ebd

Browse files
authored
Merge pull request #1653 from SciML/myb/null
Reduce allocations
2 parents c39e2f5 + 41177ba commit 7962ebd

File tree

1 file changed

+36
-13
lines changed

1 file changed

+36
-13
lines changed

src/structural_transformation/bareiss.jl

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -211,10 +211,16 @@ function bareiss!(M::AbstractMatrix{T}, swap_strategy = bareiss_colswap;
211211
end
212212

213213
function nullspace(A; col_order = nothing)
214-
column_pivots = collect(1:size(A, 2))
214+
n = size(A, 2)
215+
workspace = zeros(Int, 2 * n)
216+
column_pivots = @view workspace[1:n]
217+
pivots_cache = @view workspace[(n + 1):(2n)]
218+
@inbounds for i in 1:n
219+
column_pivots[i] = i
220+
end
215221
B = copy(A)
216222
(rank, d, column_permuted) = bareiss!(B; column_pivots)
217-
reduce_echelon!(B, rank, d)
223+
reduce_echelon!(B, rank, d, pivots_cache)
218224

219225
# The first rank entries in col_order are columns that give a basis
220226
# for the column space. The remainder give the free variables.
@@ -226,7 +232,8 @@ function nullspace(A; col_order = nothing)
226232
end
227233
end
228234

229-
N = ModelingToolkit.reduced_echelon_nullspace(rank, B)
235+
fill!(pivots_cache, 0)
236+
N = ModelingToolkit.reduced_echelon_nullspace(rank, B, pivots_cache)
230237
apply_inv_pivot_rows!(N, column_pivots)
231238
end
232239

@@ -241,18 +248,33 @@ end
241248
### Modified from AbstractAlgebra.jl
242249
###
243250
### https://github.com/Nemocas/AbstractAlgebra.jl/blob/4803548c7a945f3f7bd8c63f8bb7c79fac92b11a/LICENSE.md
244-
function reduce_echelon!(A::AbstractMatrix{T}, rank, d) where {T}
251+
function reduce_echelon!(A::AbstractMatrix{T}, rank, d,
252+
pivots_cache = zeros(Int, size(A, 2))) where {T}
245253
m, n = size(A)
246-
for i in (rank + 1):m
247-
for j in 1:n
248-
A[i, j] = zero(T)
254+
isreduced = true
255+
@inbounds for i in 1:rank
256+
for j in 1:(i - 1)
257+
if A[j, i] != zero(T)
258+
isreduced = false
259+
@goto out
260+
end
249261
end
262+
if A[i, i] != one(T)
263+
isreduced = false
264+
@goto out
265+
end
266+
end
267+
@label out
268+
@inbounds for i in (rank + 1):m, j in 1:n
269+
A[i, j] = zero(T)
250270
end
251-
if rank > 1
271+
isreduced && return A
272+
273+
@inbounds if rank > 1
252274
t = zero(T)
253275
q = zero(T)
254276
d = -d
255-
pivots = zeros(Int, n)
277+
pivots = pivots_cache
256278
np = rank
257279
j = k = 1
258280
for i in 1:rank
@@ -292,17 +314,18 @@ function reduce_echelon!(A::AbstractMatrix{T}, rank, d) where {T}
292314
return A
293315
end
294316

295-
function reduced_echelon_nullspace(rank, A::AbstractMatrix{T}) where {T}
317+
function reduced_echelon_nullspace(rank, A::AbstractMatrix{T},
318+
pivots_cache = zeros(Int, size(A, 2))) where {T}
296319
n = size(A, 2)
297320
nullity = n - rank
298321
U = zeros(T, n, nullity)
299-
if rank == 0
322+
@inbounds if rank == 0
300323
for i in 1:nullity
301324
U[i, i] = one(T)
302325
end
303326
elseif nullity != 0
304-
pivots = zeros(Int, rank)
305-
nonpivots = zeros(Int, nullity)
327+
pivots = @view pivots_cache[1:rank]
328+
nonpivots = @view pivots_cache[(rank + 1):n]
306329
j = k = 1
307330
for i in 1:rank
308331
while iszero(A[i, j])

0 commit comments

Comments
 (0)