@@ -602,6 +602,8 @@ def unextend_zero(self, parameters, variable):
602602 """
603603 result = [(domain , func ) for domain , func in parameters
604604 if func != 0 ]
605+ if len (result ) == len (self ):
606+ return self
605607 return piecewise (result , var = variable )
606608
607609 def pieces (self , parameters , variable ):
@@ -980,6 +982,17 @@ def convolution(self, parameters, variable, other):
980982 x|-->-x + 6 on (3, 4],
981983 x|-->-2*x + 10 on (4, 5]; x)
982984
985+ Some unbounded but convergent cases now work::
986+
987+ sage: p = piecewise([[(2,oo),exp(-x)]])
988+ sage: q = piecewise([[[2,3],x]])
989+ sage: p.convolution(q)
990+ piecewise(x|-->(x - 3)*e^(-2) - e^(-x + 2) on (4, 5]; x)
991+ sage: q.convolution(p)
992+ piecewise(x|-->(x - 3)*e^(-2) - e^(-x + 2) on (4, 5]; x)
993+
994+ TESTS::
995+
983996 Check that the bugs raised in :issue:`12123` are fixed::
984997
985998 sage: f = piecewise([[(-2, 2), 2]])
@@ -1003,45 +1016,56 @@ def convolution(self, parameters, variable, other):
10031016 fd , f0 = parameters [0 ]
10041017 gd , g0 = next (other .items ())
10051018 if len (f ) == 1 == len (g ):
1006- f = f .unextend_zero ()
1007- g = g .unextend_zero ()
10081019 a1 = fd [0 ].lower ()
10091020 a2 = fd [0 ].upper ()
10101021 b1 = gd [0 ].lower ()
10111022 b2 = gd [0 ].upper ()
1012- with SR .temp_var () as tt :
1013- with SR .temp_var () as uu :
1014- i1 = f0 .subs ({variable : uu })
1015- i2 = g0 .subs ({variable : tt - uu })
1016- fg1 = definite_integral (i1 * i2 , uu , a1 , tt - b1 ).subs ({tt : variable })
1017- fg2 = definite_integral (i1 * i2 , uu , tt - b2 , tt - b1 ).subs ({tt : variable })
1018- fg3 = definite_integral (i1 * i2 , uu , tt - b2 , a2 ).subs ({tt : variable })
1019- fg4 = definite_integral (i1 * i2 , uu , a1 , a2 ).subs ({tt : variable })
1020- if a1 - b1 < a2 - b2 :
1021- if a2 + b1 != a1 + b2 :
1022- h = piecewise ([[(a1 + b1 , a1 + b2 ), fg1 ],
1023- [(a1 + b2 , a2 + b1 ), fg2 ],
1024- [(a2 + b1 , a2 + b2 ), fg3 ]])
1025- else :
1026- h = piecewise ([[(a1 + b1 , a1 + b2 ), fg1 ],
1027- [(a1 + b2 , a2 + b2 ), fg3 ]])
1023+ a1b1 = a1 + b1
1024+ a2b2 = a2 + b2
1025+ delta_a = a2 - a1
1026+ delta_b = b2 - b1
1027+
1028+ # this fails in some unbounded cases:
1029+ a1b2 = a1 + b2
1030+ a2b1 = a2 + b1
1031+
1032+ todo = []
1033+ if delta_a > delta_b :
1034+ if a1b2 is not minus_infinity :
1035+ todo .append ((a1b1 , a1b2 , a1 , variable - b1 ))
1036+ todo .append ((a1b2 , a2b1 , variable - b2 , variable - b1 ))
1037+ if a2b1 is not infinity :
1038+ todo .append ((a2b1 , a2b2 , variable - b2 , a2 ))
1039+ elif delta_a < delta_b :
1040+ if a2b1 is not minus_infinity :
1041+ todo .append ((a1b1 , a2b1 , a1 , variable - b1 ))
1042+ todo .append ((a2b1 , a1b2 , a1 , a2 ))
1043+ if a1b2 is not infinity :
1044+ todo .append ((a1b2 , a2b2 , variable - b2 , a2 ))
10281045 else :
1029- if a1 + b2 != a2 + b1 :
1030- h = piecewise ([[(a1 + b1 , a2 + b1 ), fg1 ],
1031- [(a2 + b1 , a1 + b2 ), fg4 ],
1032- [(a1 + b2 , a2 + b2 ), fg3 ]])
1033- else :
1034- h = piecewise ([[(a1 + b1 , a2 + b1 ), fg1 ],
1035- [(a2 + b1 , a2 + b2 ), fg3 ]])
1036- return (piecewise ([[(minus_infinity , infinity ), 0 ]]).piecewise_add (h )).unextend_zero ()
1037-
1038- if len (f ) > 1 or len (g ) > 1 :
1039- z = piecewise ([[(0 , 0 ), 0 ]])
1040- for fpiece in f .pieces ():
1041- for gpiece in g .pieces ():
1042- h = gpiece .convolution (fpiece )
1043- z = z .piecewise_add (h )
1044- return z .unextend_zero ()
1046+ if a2b1 is not minus_infinity :
1047+ todo .append ((a1b1 , a2b1 , a1 , variable - b1 ))
1048+ todo .append ((a2b1 , a2b2 , variable - b2 , a2 ))
1049+
1050+ if not todo :
1051+ raise ValueError ("no domain of integration" )
1052+
1053+ with SR .temp_var () as uu :
1054+ i1 = f0 .subs ({variable : uu })
1055+ i2 = g0 .subs ({variable : variable - uu })
1056+ expr = i1 * i2
1057+ h = piecewise ([[(start , stop ),
1058+ definite_integral (expr , uu , mini , maxi )]
1059+ for start , stop , mini , maxi in todo ])
1060+ flat_zero = piecewise ([[(minus_infinity , infinity ), 0 ]])
1061+ return (flat_zero .piecewise_add (h )).unextend_zero () # why ?
1062+
1063+ z = piecewise ([[(0 , 0 ), 0 ]])
1064+ for fpiece in f .pieces ():
1065+ for gpiece in g .pieces ():
1066+ h = gpiece .convolution (fpiece )
1067+ z = z .piecewise_add (h )
1068+ return z .unextend_zero ()
10451069
10461070 def trapezoid (self , parameters , variable , N ):
10471071 """
0 commit comments