@@ -14,16 +14,19 @@ function promote_operation_fallback(
1414 # `zero` is not defined for `AbstractArray` so the fallback would fail with a cryptic MethodError.
1515 # We replace it by a more helpful error here.
1616 return error (
17- " `promote_operation($op , $x , $y )` not implemented yet, please report this." ,
17+ " `promote_operation($op , $x , $y )` not implemented yet, please report " *
18+ " this." ,
1819 )
1920end
21+
2022function promote_operation_fallback (
2123 :: typeof (/ ),
2224 :: Type{S} ,
2325 :: Type{T} ,
2426) where {S,T}
2527 return typeof (zero (S) / oneunit (T))
2628end
29+
2730# Julia v1.0.x has trouble with inference with the `Vararg` method, see
2831# https://travis-ci.org/jump-dev/JuMP.jl/jobs/617606373
2932function promote_operation_fallback (
@@ -33,13 +36,16 @@ function promote_operation_fallback(
3336) where {F<: Function ,S,T}
3437 return typeof (op (zero (S), zero (T)))
3538end
39+
3640function promote_operation_fallback (
3741 op:: F ,
3842 args:: Vararg{Type,N} ,
3943) where {F<: Function ,N}
4044 return typeof (op (zero .(args)... ))
4145end
46+
4247promote_operation_fallback (:: typeof (* ), :: Type{T} ) where {T} = T
48+
4349function promote_operation_fallback (
4450 :: typeof (* ),
4551 :: Type{S} ,
@@ -50,17 +56,20 @@ function promote_operation_fallback(
5056 return promote_operation (* , promote_operation (* , S, T), U, args... )
5157end
5258
53- # `Vararg` gives extra allocations on Julia v1.3, see https://travis-ci.com/jump-dev/MutableArithmetics.jl/jobs/260666164#L215-L238
59+ # `Vararg` gives extra allocations on Julia v1.3, see
60+ # https://travis-ci.com/jump-dev/MutableArithmetics.jl/jobs/260666164#L215-L238
5461function promote_operation_fallback (op:: AddSubMul , T:: Type , x:: Type , y:: Type )
5562 return promote_operation (add_sub_op (op), T, promote_operation (* , x, y))
5663end
64+
5765function promote_operation_fallback (
5866 op:: AddSubMul ,
5967 x:: Type{<:AbstractArray} ,
6068 y:: Type{<:AbstractArray} ,
6169)
6270 return promote_operation (add_sub_op (op), x, y)
6371end
72+
6473function promote_operation_fallback (
6574 op:: Union{AddSubMul,typeof(add_dot)} ,
6675 T:: Type ,
@@ -90,7 +99,8 @@ function promote_operation(
9099 α:: Type{<:Number} ,
91100)
92101 return error (
93- " Operation `$op ` between `$A ` and `$α ` is not allowed. You should use broadcast." ,
102+ " Operation `$op ` between `$A ` and `$α ` is not allowed. You should " *
103+ " use broadcast." ,
94104 )
95105end
96106function promote_operation (
@@ -99,7 +109,8 @@ function promote_operation(
99109 A:: Type{<:Array} ,
100110)
101111 return error (
102- " Operation `$op ` between `$α ` and `$A ` is not allowed. You should use broadcast." ,
112+ " Operation `$op ` between `$α ` and `$A ` is not allowed. You should " *
113+ " use broadcast." ,
103114 )
104115end
105116
@@ -152,6 +163,7 @@ function operate end
152163# API without altering `x` and `y`. If it is not the case, implement a
153164# custom `operate` method.
154165operate (:: typeof (- ), x) = - x
166+
155167function operate (
156168 op:: Union{typeof(+),typeof(*),AddSubMul,typeof(add_dot)} ,
157169 x,
@@ -160,17 +172,21 @@ function operate(
160172) where {N}
161173 return op (x, y, args... )
162174end
175+
163176operate (op:: Union{typeof(-),typeof(/)} , x, y) where {N} = op (x, y)
177+
164178operate (:: typeof (convert), :: Type{T} , x) where {T} = convert (T, x)
179+
165180operate (:: typeof (convert), :: Type{T} , x:: T ) where {T} = copy_if_mutable (x)
166181
167182operate (:: Union{typeof(+),typeof(*)} , x) = copy_if_mutable (x)
168183
169- # We could only give `typeof(x)` to `zero` and `one` to be sure that modifying the
170- # returned object cannot alter `x` but for some objects, `one` and `zero` depends
171- # on some values of the fields (e.g. square matrices), elements of the cyclic group
172- # of order `n` (`n` is one of the field).
184+ # We could only give `typeof(x)` to `zero` and `one` to be sure that modifying
185+ # the returned object cannot alter `x` but for some objects, `one` and `zero`
186+ # depends on some values of the fields (e.g. square matrices), elements of the
187+ # cyclic group of order `n` (`n` is one of the field).
173188operate (:: typeof (zero), x) = zero (x)
189+
174190operate (:: typeof (one), x) = one (x)
175191
176192# Define Traits
@@ -212,9 +228,11 @@ function mutability(T::Type, op, args::Vararg{Type,N}) where {N}
212228 return IsNotMutable ()
213229 end
214230end
231+
215232function mutability (x, op, args:: Vararg{Any,N} ) where {N}
216233 return mutability (typeof (x), op, typeof .(args)... )
217234end
235+
218236mutability (:: Type ) = IsNotMutable ()
219237
220238"""
@@ -231,8 +249,11 @@ cannot be modified though the MultableArithmetics's API, however, it calls
231249be mutated.
232250"""
233251function mutable_copy end
252+
234253mutable_copy (A:: AbstractArray ) = mutable_copy .(A)
254+
235255copy_if_mutable_fallback (:: IsNotMutable , x) = x
256+
236257copy_if_mutable_fallback (:: IsMutable , x) = mutable_copy (x)
237258
238259"""
@@ -249,14 +270,21 @@ copy_if_mutable(x) = copy_if_mutable_fallback(mutability(typeof(x)), x)
249270function operate_to_fallback! (:: IsNotMutable , output, op:: Function , args... )
250271 throw (
251272 ArgumentError (
252- " Cannot call `operate_to!(::$(typeof (output)) , $op , ::$(join (typeof .(args), " , ::" )) )` as objects of type `$(typeof (output)) ` cannot be modifed to equal the result of the operation. Use `operate_to!!` instead which returns the value of the result (possibly modifying the first argument) to write generic code that also works when the type cannot be modified." ,
273+ " Cannot call `operate_to!(::$(typeof (output)) , $op , " *
274+ " ::$(join (typeof .(args), " , ::" )) )` as objects of type " *
275+ " `$(typeof (output)) ` cannot be modifed to equal the result of " *
276+ " the operation. Use `operate_to!!` instead which returns the " *
277+ " value of the result (possibly modifying the first argument) to " *
278+ " write generic code that also works when the type cannot be " *
279+ " modified." ,
253280 ),
254281 )
255282end
256283
257284function operate_to_fallback! (:: IsMutable , output, op:: AddSubMul , x, y)
258285 return operate_to! (output, add_sub_op (op), x, y)
259286end
287+
260288function operate_to_fallback! (:: IsMutable , output, op:: Function , args... )
261289 return error (
262290 " `operate_to!(::$(typeof (output)) , $op , ::" ,
@@ -291,16 +319,22 @@ function operate_to!(output, op::F, args::Vararg{Any,N}) where {F<:Function,N}
291319end
292320
293321function operate_fallback! (:: IsNotMutable , op:: Function , args... )
294- throw (
322+ return throw (
295323 ArgumentError (
296- " Cannot call `operate!($op , ::$(join (typeof .(args), " , ::" )) )` as objects of type `$(typeof (args[1 ])) ` cannot be modifed to equal the result of the operation. Use `operate!!` instead which returns the value of the result (possibly modifying the first argument) to write generic code that also works when the type cannot be modified." ,
324+ " Cannot call `operate!($op , ::$(join (typeof .(args), " , ::" )) )` " *
325+ " as objects of type `$(typeof (args[1 ])) ` cannot be modifed to " *
326+ " equal the result of the operation. Use `operate!!` instead " *
327+ " which returns the value of the result (possibly modifying the " *
328+ " first argument) to write generic code that also works when the " *
329+ " type cannot be modified." ,
297330 ),
298331 )
299332end
300333
301334function operate_fallback! (:: IsMutable , op:: AddSubMul , x, y)
302335 return operate! (add_sub_op (op), x, y)
303336end
337+
304338function operate_fallback! (:: IsMutable , op:: Function , args... )
305339 return error (
306340 " `operate!($op , ::" ,
313347 operate!(op::Function, args...)
314348
315349Modify the value of `args[1]` to be equal to the value of `op(args...)`. Can
316- only be called if `mutability(args[1], op, args...)` returns [`IsMutable`](@ref).
350+ only be called if `mutability(args[1], op, args...)` returns
351+ [`IsMutable`](@ref).
317352"""
318353function operate! (op:: F , args:: Vararg{Any,N} ) where {F<: Function ,N}
319354 return operate_fallback! (mutability (args[1 ], op, args... ), op, args... )
@@ -330,7 +365,13 @@ function buffered_operate_to_fallback!(
330365)
331366 throw (
332367 ArgumentError (
333- " Cannot call `buffered_operate_to!(::$(typeof (buffer)) , ::$(typeof (output)) , $op , ::$(join (typeof .(args), " , ::" )) )` as objects of type `$(typeof (output)) ` cannot be modifed to equal the result of the operation. Use `buffered_operate_to!!` instead which returns the value of the result (possibly modifying the first argument) to write generic code that also works when the type cannot be modified." ,
368+ " Cannot call `buffered_operate_to!(::$(typeof (buffer)) , " *
369+ " ::$(typeof (output)) , $op , ::$(join (typeof .(args), " , ::" )) )` " *
370+ " as objects of type `$(typeof (output)) ` cannot be modifed to " *
371+ " equal the result of the operation. Use `buffered_operate_to!!` " *
372+ " instead which returns the value of the result (possibly " *
373+ " modifying the first argument) to write generic code that also " *
374+ " works when the type cannot be modified." ,
334375 ),
335376 )
336377end
@@ -343,9 +384,8 @@ function buffered_operate_to_fallback!(
343384 args... ,
344385)
345386 return error (
346- " `buffered_operate_to!(::$(typeof (buffer)) , ::$(typeof (output)) , $op , ::" ,
347- join (typeof .(args), " , ::" ),
348- " )` is not implemented." ,
387+ " `buffered_operate_to!(::$(typeof (buffer)) , ::$(typeof (output)) , " *
388+ " $op , ::$(join (typeof .(args), " , ::" )) )` is not implemented." ,
349389 )
350390end
351391
@@ -397,7 +437,13 @@ function buffered_operate_fallback!(
397437)
398438 throw (
399439 ArgumentError (
400- " Cannot call `buffered_operate!(::$(typeof (buffer)) , $op , ::$(join (typeof .(args), " , ::" )) )` as objects of type `$(typeof (args[1 ])) ` cannot be modifed to equal the result of the operation. Use `buffered_operate!!` instead which returns the value of the result (possibly modifying the first argument) to write generic code that also works when the type cannot be modified." ,
440+ " Cannot call `buffered_operate!(::$(typeof (buffer)) , $op , " *
441+ " ::$(join (typeof .(args), " , ::" )) )` as objects of type " *
442+ " `$(typeof (args[1 ])) ` cannot be modifed to equal the result of " *
443+ " the operation. Use `buffered_operate!!` instead which returns " *
444+ " the value of the result (possibly modifying the first argument) " *
445+ " to write generic code that also works when the type cannot be " *
446+ " modified." ,
401447 ),
402448 )
403449end
@@ -439,6 +485,7 @@ possibly modifying `buffer`. Can only be called if
439485`mutability(args[1], op, args...)` returns [`IsMutable`](@ref).
440486"""
441487function buffered_operate! end
488+
442489function buffered_operate! (
443490 buffer,
444491 op:: F ,
@@ -469,6 +516,7 @@ function operate_to_fallback!!(
469516) where {F<: Function ,N}
470517 return operate (op, args... )
471518end
519+
472520function operate_to_fallback!! (
473521 :: IsMutable ,
474522 output,
@@ -494,6 +542,7 @@ function operate_fallback!!(
494542) where {F<: Function ,N}
495543 return operate (op, args... )
496544end
545+
497546function operate_fallback!! (
498547 :: IsMutable ,
499548 op:: F ,
@@ -531,6 +580,7 @@ function buffered_operate_to_fallback!!(
531580) where {F<: Function ,N}
532581 return operate (op, args... )
533582end
583+
534584function buffered_operate_to_fallback!! (
535585 :: IsMutable ,
536586 buffer,
@@ -567,6 +617,7 @@ function buffered_operate_fallback!!(
567617) where {F<: Function ,N}
568618 return operate (op, args... )
569619end
620+
570621function buffered_operate_fallback!! (
571622 :: IsMutable ,
572623 buffer,
@@ -578,29 +629,27 @@ end
578629
579630# For most types, `dot(b, c) = adjoint(b) * c`.
580631promote_operation_fallback (:: typeof (adjoint), a:: Type ) = a
632+
581633function promote_operation_fallback (
582634 :: typeof (LinearAlgebra. dot),
583635 b:: Type ,
584636 c:: Type ,
585637)
586638 return promote_operation (* , promote_operation (adjoint, b), c)
587639end
640+
588641function buffer_for (:: typeof (add_dot), a:: Type , b:: Type , c:: Type )
589642 return buffer_for (add_mul, a, promote_operation (adjoint, b), c)
590643end
591- function operate_to_fallback! (
592- :: IsMutable ,
593- output,
594- :: typeof (add_dot),
595- a,
596- b,
597- c,
598- ) where {N}
644+
645+ function operate_to_fallback! (:: IsMutable , output, :: typeof (add_dot), a, b, c)
599646 return operate_to! (output, add_mul, a, adjoint (b), c)
600647end
601- function operate_fallback! (:: IsMutable , :: typeof (add_dot), a, b, c) where {N}
648+
649+ function operate_fallback! (:: IsMutable , :: typeof (add_dot), a, b, c)
602650 return operate! (add_mul, a, adjoint (b), c)
603651end
652+
604653function buffered_operate_to_fallback! (
605654 :: IsMutable ,
606655 buffer,
@@ -612,6 +661,7 @@ function buffered_operate_to_fallback!(
612661)
613662 return buffered_operate_to! (buffer, output, add_mul, a, adjoint (b), c)
614663end
664+
615665function buffered_operate_fallback! (
616666 :: IsMutable ,
617667 buffer,
0 commit comments