@@ -511,7 +511,7 @@ a single n-ary operation.
511511
512512Nonlinear expressions created using operator overloading can be deeply nested
513513and unbalanced. For example, `prod(x for i in 1:4)` creates
514- `*(x, *(x, *( x, x)) )` instead of the more preferable `*(x, x, x, x)`.
514+ `*(*(*( x, x), x, x)` instead of the more preferable `*(x, x, x, x)`.
515515
516516## Example
517517
@@ -536,27 +536,35 @@ function flatten!(expr::GenericNonlinearExpr{V}) where {V}
536536 return expr
537537 end
538538 stack = Tuple{GenericNonlinearExpr{V},Int,GenericNonlinearExpr{V}}[]
539- for i in length (expr. args): - 1 : 1
539+ for i in 1 : length (expr. args)
540540 if _needs_flatten (expr, expr. args[i])
541541 push! (stack, (expr, i, expr. args[i]))
542542 end
543543 end
544544 while ! isempty (stack)
545545 parent, i, arg = pop! (stack)
546546 if parent. head in (:+ , :* ) && arg. head == parent. head
547- n = length (parent. args)
548- resize! (parent. args, n + length (arg. args) - 1 )
549- for j in length (arg. args): - 1 : 1
550- parent_index = j == 1 ? i : n + j - 1
547+ m, n = length (arg. args), length (parent. args)
548+ # We're going to splice the `m` args of the child into
549+ # `parent.args[i:i+m-1]`. To do so, extend the args to make space:
550+ resize! (parent. args, n + (m - 1 ))
551+ # and then shift the parent args along to make room:
552+ for j in n: - 1 : (i+ 1 )
553+ parent. args[m+ j- 1 ] = parent. args[j]
554+ end
555+ # Now we can put each child arg into the parent.
556+ for j in 1 : m
557+ parent_index = i + j - 1
551558 if _needs_flatten (parent, arg. args[j])
559+ # The child needs flattening itself
552560 push! (stack, (parent, parent_index, arg. args[j]))
553561 else
554562 parent. args[parent_index] = arg. args[j]
555563 end
556564 end
557565 else
558566 parent. args[i] = arg
559- for j in length (arg. args): - 1 : 1
567+ for j in 1 : length (arg. args)
560568 if _needs_flatten (arg, arg. args[j])
561569 push! (stack, (arg, j, arg. args[j]))
562570 end
0 commit comments