@@ -117,37 +117,61 @@ with_logabsdet_jacobian(f, x) = NoLogAbsDetJacobian(f, x)
117117end
118118
119119
120- function _with_ladj_on_mapped (@nospecialize (map_or_bc:: F ), y_with_ladj:: NoLogAbsDetJacobian ) where {F<: Union{typeof(map),typeof(broadcast)} }
121- return y_with_ladj
122- end
120+ _with_ladj_on_mapped (y_with_ladj:: NoLogAbsDetJacobian ) = y_with_ladj
123121
124- function _with_ladj_on_mapped (map_or_bc :: F , y_with_ladj:: Tuple{Any,Real} ) where {F <: Union{typeof(map),typeof(broadcast)} }
125- return y_with_ladj
126- end
122+ _with_ladj_on_mapped (y_with_ladj:: Tuple{Any,Real} ) = y_with_ladj
123+
124+ _with_ladj_on_mapped ( :: AbstractArray{T} ) where {T <: NoLogAbsDetJacobian } = T ()
127125
128126_get_all_first (x) = map (first, x)
129- # Use x -> x[2] instead of last, using last causes horrible performance in Zygote here:
130- _sum_over_second (x) = sum (x -> x[2 ], x)
127+ _get_second (x) = x[2 ]
128+ # Use _get_second instead of last, using last causes horrible performance in Zygote here:
129+ _sum_over_second (x) = sum (_get_second, x)
131130
132- function _with_ladj_on_mapped (map_or_bc :: F , y_with_ladj) where {F <: Union{typeof(map),typeof(broadcast)} }
131+ function _with_ladj_on_mapped (y_with_ladj)
133132 y = _get_all_first (y_with_ladj)
134133 ladj = _sum_over_second (y_with_ladj)
135134 (y, ladj)
136135end
137136
137+ _combine_y_ladj (l:: NoLogAbsDetJacobian , @nospecialize (r:: NoLogAbsDetJacobian )) = l
138+ _combine_y_ladj (l:: NoLogAbsDetJacobian , @nospecialize (r:: Tuple{Any,Real} )) = l
139+ _combine_y_ladj (@nospecialize (l:: Tuple{Any,Real} ), r:: NoLogAbsDetJacobian ) = r
140+ _combine_y_ladj (l:: Tuple{Any,Real} , r:: Tuple{Any,Real} ) = ((l[1 ]. .. , r[1 ]), l[2 ] + r[2 ])
141+
142+ function _with_ladj_on_mapped (y_with_ladj:: Tuple {NoLogAbsDetJacobian, Vararg{Union{NoLogAbsDetJacobian, Tuple{Any,Real}}}})
143+ return first (y_with_ladj)
144+ end
145+
146+ @static if VERSION < v " 1.6"
147+ # Hand-rolled foldl, foldl over tuples is not inferrable on Julia < 1.6:
148+ _foldl_combine_y_ladj (acc) = acc
149+ _foldl_combine_y_ladj (acc, b, bs... ) = _foldl_combine_y_ladj (_combine_y_ladj (acc, b), bs... )
150+
151+ function _with_ladj_on_mapped (y_with_ladj:: Tuple {Tuple{Any,Real}, Vararg{Union{NoLogAbsDetJacobian, Tuple{Any,Real}}}})
152+ a = first (y_with_ladj)
153+ return _foldl_combine_y_ladj (((a[1 ],), a[2 ]), Base. tail (y_with_ladj)... )
154+ end
155+ else
156+ function _with_ladj_on_mapped (y_with_ladj:: Tuple {Tuple{Any,Real}, Vararg{Union{NoLogAbsDetJacobian, Tuple{Any,Real}}}})
157+ a, bs = first (y_with_ladj), Base. tail (y_with_ladj)
158+ return foldl (_combine_y_ladj, bs, init = ((a[1 ],), a[2 ]))
159+ end
160+ end
161+
138162@static if VERSION >= v " 1.6"
139163 function with_logabsdet_jacobian (mapped_f:: Base.Broadcast.BroadcastFunction , X)
140164 f = mapped_f. f
141165 y_with_ladj = broadcast (Base. Fix1 (with_logabsdet_jacobian, f), X)
142- _with_ladj_on_mapped (broadcast, y_with_ladj)
166+ _with_ladj_on_mapped (y_with_ladj)
143167 end
144168end
145169
146170function with_logabsdet_jacobian (mapped_f:: Base.Fix1{<:Union{typeof(map),typeof(broadcast)}} , X)
147171 map_or_bc = mapped_f. f
148172 f = mapped_f. x
149173 y_with_ladj = map_or_bc (Base. Fix1 (with_logabsdet_jacobian, f), X)
150- _with_ladj_on_mapped (map_or_bc, y_with_ladj)
174+ _with_ladj_on_mapped (y_with_ladj)
151175end
152176
153177
0 commit comments