231
231
function reduce! (mm:: SparseMatrixCLIL , ag:: AliasGraph )
232
232
dels = Int[]
233
233
for (i, rs) in enumerate (mm. row_cols)
234
- p = i == 7
235
234
rvals = mm. row_vals[i]
236
235
j = 1
237
236
while j <= length (rs)
@@ -244,9 +243,9 @@ function reduce!(mm::SparseMatrixCLIL, ag::AliasGraph)
244
243
inc = coeff * rvals[j]
245
244
i = searchsortedfirst (rs, alias)
246
245
if i > length (rs) || rs[i] != alias
247
- if i <= j
248
- j += 1
249
- end
246
+ # if we add a variable to what we already visited, make sure
247
+ # to bump the cursor.
248
+ j += i <= j
250
249
insert! (rs, i, alias)
251
250
insert! (rvals, i, inc)
252
251
else
@@ -272,11 +271,11 @@ struct InducedAliasGraph
272
271
ag:: AliasGraph
273
272
invag:: SimpleDiGraph{Int}
274
273
var_to_diff:: DiffGraph
275
- visited:: BitVector
274
+ visited:: BitSet
276
275
end
277
276
278
277
function InducedAliasGraph (ag, invag, var_to_diff)
279
- InducedAliasGraph (ag, invag, var_to_diff, falses ( nv (invag) ))
278
+ InducedAliasGraph (ag, invag, var_to_diff, BitSet ( ))
280
279
end
281
280
282
281
struct IAGNeighbors
286
285
287
286
function Base. iterate (it:: IAGNeighbors , state = nothing )
288
287
@unpack ag, invag, var_to_diff, visited = it. iag
289
- callback! = let visited = visited
290
- var -> visited[var] = true
291
- end
288
+ callback! = Base. Fix1 (push!, visited)
292
289
if state === nothing
293
290
v, lv = extreme_var (var_to_diff, it. v, 0 )
294
291
used_ag = false
@@ -298,13 +295,13 @@ function Base.iterate(it::IAGNeighbors, state = nothing)
298
295
end
299
296
300
297
v, level, used_ag, nb, nit = state
301
- visited[v] && return nothing
298
+ v in visited && return nothing
302
299
while true
303
300
@label TRYAGIN
304
301
if used_ag
305
302
if nit != = nothing
306
303
n, ns = nit
307
- if ! visited[n]
304
+ if ! (n in visited)
308
305
n, lv = extreme_var (var_to_diff, n, level)
309
306
extreme_var (var_to_diff, n, nothing , Val (false ), callback = callback!)
310
307
nit = iterate (nb, ns)
@@ -316,7 +313,7 @@ function Base.iterate(it::IAGNeighbors, state = nothing)
316
313
# We don't care about the alising value because we only use this to
317
314
# find the root of the tree.
318
315
if (_n = get (ag, v, nothing )) != = nothing && (n = _n[2 ]) > 0
319
- if ! visited[n]
316
+ if ! (n in visited)
320
317
n, lv = extreme_var (var_to_diff, n, level)
321
318
extreme_var (var_to_diff, n, nothing , Val (false ), callback = callback!)
322
319
return n => lv, (v, level, used_ag, nb, nit)
@@ -325,7 +322,7 @@ function Base.iterate(it::IAGNeighbors, state = nothing)
325
322
@goto TRYAGIN
326
323
end
327
324
end
328
- visited[v] = true
325
+ push! ( visited, v)
329
326
(v = var_to_diff[v]) === nothing && return nothing
330
327
level += 1
331
328
used_ag = false
@@ -349,11 +346,12 @@ function _find_root!(iag::InducedAliasGraph, v::Integer, level = 0)
349
346
end
350
347
351
348
function find_root! (iag:: InducedAliasGraph , v:: Integer )
352
- ret = _find_root! (iag, v)
353
- fill! (iag. visited, false )
354
- ret
349
+ clear_visited! (iag)
350
+ _find_root! (iag, v)
355
351
end
356
352
353
+ clear_visited! (iag:: InducedAliasGraph ) = (empty! (iag. visited); iag)
354
+
357
355
struct RootedAliasTree
358
356
iag:: InducedAliasGraph
359
357
root:: Int
@@ -376,9 +374,6 @@ function Base.iterate(it::StatefulAliasBFS, queue = (eltype(it)[(1, 0, it.t)]))
376
374
coeff, lv, t = popfirst! (queue)
377
375
nextlv = lv + 1
378
376
for (coeff′, c) in children (t)
379
- # FIXME : use the visited cache!
380
- # A "cycle" might occur when we have `x ~ D(x)`.
381
- nodevalue (c) == t. root && continue
382
377
# -1 <= coeff <= 1
383
378
push! (queue, (coeff * coeff′, nextlv, c))
384
379
end
392
387
function Base. iterate (c:: RootedAliasChildren , s = nothing )
393
388
rat = c. t
394
389
@unpack iag, root = rat
395
- @unpack ag, invag, var_to_diff, visited = iag
390
+ @unpack visited = iag
391
+ push! (visited, root)
392
+ it = _iterate (c, s)
393
+ it === nothing && return nothing
394
+ while true
395
+ node = nodevalue (it[1 ][2 ])
396
+ if node in visited
397
+ it = _iterate (c, it[2 ])
398
+ it === nothing && return nothing
399
+ else
400
+ push! (visited, node)
401
+ return it
402
+ end
403
+ end
404
+ end
405
+
406
+ @inline function _iterate (c:: RootedAliasChildren , s = nothing )
407
+ rat = c. t
408
+ @unpack iag, root = rat
409
+ @unpack ag, invag, var_to_diff = iag
396
410
(iszero (root) || (root = var_to_diff[root]) === nothing ) && return nothing
397
411
if s === nothing
398
412
stage = 1
@@ -516,7 +530,6 @@ function simple_aliases!(ag, graph, var_to_diff, mm_orig, only_algebraic, irredu
516
530
irreducibles)
517
531
518
532
# Step 2: Simplify the system using the Bareiss factorization
519
- ks = keys (ag)
520
533
for v in setdiff (solvable_variables, @view pivots[1 : rank1])
521
534
ag[v] = 0
522
535
end
@@ -624,6 +637,7 @@ function alias_eliminate_graph!(graph, var_to_diff, mm_orig::SparseMatrixCLIL)
624
637
end
625
638
end
626
639
max_lv = 0
640
+ clear_visited! (iag)
627
641
for (coeff, lv, t) in StatefulAliasBFS (RootedAliasTree (iag, r))
628
642
max_lv = max (max_lv, lv)
629
643
v = nodevalue (t)
@@ -692,7 +706,7 @@ function locally_structure_simplify!(adj_row, pivot_var, ag)
692
706
iszero (pivot_val) && return false
693
707
694
708
nirreducible = 0
695
- alias_candidate:: Union{Int, Pair{Int, Int}} = 0
709
+ alias_candidate:: Pair{Int, Int} = 0 => 0
696
710
697
711
# N.B.: Assumes that the non-zeros iterator is robust to modification
698
712
# of the underlying array datastructure.
0 commit comments