home *** CD-ROM | disk | FTP | other *** search
- (* :Mathematica Version: 2.1 *)
-
- (* :Context: Calculus` *)
-
- (* :Title: DiracDelta *)
-
- (* :Author: E.C.Martin *)
-
- (* :Summary:
- Defines the UnitStep function and its generalized derivative, DiracDelta.
- Provides Limit, Integrate, and Derivative rules for UnitStep and
- DiracDelta.
- *)
-
- (* :Keywords: distribution, generalized function, Dirac, delta, Heaviside, step *)
-
- (* :Package Version: 1.0 *)
-
- (* :History: original version 1/92 ECM, WRI. *)
-
-
- (* :Discussion:
-
- The Laplace transform is frequently defined as an integral from 0- to
- infinity. The definite integral rule defined in this package for integrals
- containing DiracDelta and UnitStep implements instead an integral from 0+
- to infinity:
-
- Integrate[DiracDelta[t] Exp[-s t], {t, 0, Infinity}]
-
- The expected result for the most common definition of the Laplace transform
- of DiracDelta is 1, but this integral returns 0. In order to implement the
- common definition of the Laplace transform, the lower limit of the integral
- must be approached from the left:
-
- int = Integrate[DiracDelta[t] Exp[-s t], t]
-
- Limit[int, t->Infinity] - Limit[int, t->0, Direction->1]
-
- The behavior of the definite integral rule defined in this package is
- directly related to the default behavior of the built-in Limit function.
-
- *)
-
- (* :Sources: "Generalized Functions", R.F.Hoskins, Ellis Horwood Limited, 1979.
- "Theory of Distributions, the Sequential Approach", P.Antosik,
- J.Mikusinski, R.Sikorski, Elsevier Scientific, 1973.
- *)
-
- (* :Warning: Should the meaning of "Direction -> Automatic" change for
- the built-in Limit, then corresponding changes need to be made to
- Limit rules in this package.
- Definitions for D, Derivative, Limit, Integrate, and Abs are affected by
- loading this package.
- *)
-
-
- BeginPackage["Calculus`DiracDelta`"]
-
- Unprotect[ UnitStep, DiracDelta ]
-
- Map[Clear, {UnitStep, DiracDelta}]
-
- UnitStep::usage =
- "UnitStep[x] is a function that is 1 for x > 0 and 0 for x < 0.
- UnitStep[x1, x2, ...] is 1 for (x1 > 0) && (x2 > 0) && ... and 0 for
- (x1 < 0) || (x2 < 0) || ... ."
-
- DiracDelta::usage =
- "DiracDelta[x] is a distribution that is 0 for x != 0 and satisfies
- Integrate[DiracDelta[x], {x, -Infinity, Infinity}] = 1.
- DiracDelta[x1, x2, ...] is a distribution that is 0 for x1 != 0 ||
- x2 != 0 || ... and satisfies Integrate[DiracDelta[x1, x2, ...],
- {x1, -Infinity, Infinity}, {x2, -Infinity, Infinity}, ...] = 1."
-
- ZeroValue::usage =
- "ZeroValue is an option used to specify the value of UnitStep when one or more
- of the arguments are zero. In particular, UnitStep[x1, x2, ..., ZeroValue -> 1]
- is 1 for (x1 >= 0) && (x2 >= 0) && ... and UnitStep[x1, x2, ..., ZeroValue -> 0]
- is 0 for (x1 <= 0) || (x2 <= 0) || ... ."
-
- SimplifyUnitStep::usage =
- "SimplifyUnitStep[expr] returns a form of expr with fewer instances of UnitStep."
-
- SimplifyDiracDelta::usage =
- "SimplifyDiracDelta[expr] simplifies a zero distribution in expr to 0."
-
- Begin["`Private`"]
-
- Attributes[UnitStep] = Attributes[DiracDelta] = Orderless
-
- (********************************* DiracDelta *********************************)
-
- DiracDelta[x__] := 0 /; !Apply[And, Map[(#==0)&, {x}]]
-
- Unprotect[Derivative]
- Derivative[n__Integer?NonNegative][DiracDelta][x__] :=
- 0 /; !Apply[And, Map[(#==0)&, {x}]]
- Protect[Derivative]
-
- (********************************* UnitStep ***********************************)
-
- Options[UnitStep] = {ZeroValue -> 1}
- ZeroValue::zerov =
- "Warning: `` must be None or a number between 0 and 1. ZeroValue default
- assumed."
-
- UnitStep[x__, ___Rule] := 0 /; Apply[Or, Negative[{x}]]
-
- (* Handling an illegal ZeroValue. *)
-
- UnitStep[x__, ZeroValue -> k_] :=
- (Message[ZeroValue::zerov, k];
- UnitStep[x]) /; !(k === None || (NumberQ[N[k]] && 0 <= N[k] <= 1))
-
- (* Some zero arguments. *)
-
- UnitStep[x__?RuleFreeQ, r___Rule] :=
- Module[{k = ZeroValue /. {r} /. Options[UnitStep], nk, select, comp},
- (comp = Complement[{x}, select];
- k^Length[select] If[comp === {}, 1, Apply[UnitStep, Join[comp, {r}]]]) /;
- NumberQ[nk = N[k]] && 0 <= nk <= 1 &&
- Length[select = Select[{x}, N[#]==0&]] > 0
- ]
-
- (* Some positive arguments. *)
-
- UnitStep[x__?RuleFreeQ, r___Rule] :=
- Module[{select, comp},
- (comp = Complement[{x}, select];
- If[comp === {}, 1, Apply[UnitStep, Join[comp, {r}]]]
- ) /; Length[select = Select[{x}, N[#] > 0&]] > 0
- ]
-
- (* Power rule for ZeroValue equal to 0 or 1. *)
-
- UnitStep /: UnitStep[f__?RuleFreeQ,
- r___Rule]^a_?((NumberQ[#] && Positive[#])&) :=
- Module[{nk = N[ZeroValue /. {r} /. Options[UnitStep]]},
- UnitStep[f, r] /; (NumberQ[nk] && (nk === 1. || nk === 0))
- ]
-
-
- (****************************** limits, linearity ***************************)
-
- Unprotect[Limit]
-
- Limit[f_, x_ -> c_, dir___] :=
- Module[{result},
- Limit[result, x -> c, dir] /;
- (result = Collect[f, Union[Cases[{f}, UnitStep[__], Infinity],
- Cases[{f}, DiracDelta[__], Infinity],
- Cases[{f}, Derivative[__][DiracDelta][__], Infinity]]];
- !SameQ[f, result])
- ] /; !(FreeQ[f, UnitStep] && FreeQ[f, DiracDelta])
-
- Limit[a_. Derivative[n__Integer?NonNegative][DiracDelta][f__] + b_.,
- x_ -> c_, dir___] :=
- Module[{lima, limb, limdeltader},
- If[limdeltader == 0 && !FreeQ[lima, DirectedInfinity],
- limb,
- lima limdeltader + limb] /;
- (FreeQ[{lima, limb, limdeltader} =
- Limit[{a, b, Derivative[n][DiracDelta][f]}, x->c, dir], Limit] &&
- !(limdeltader != 0 &&
- !FreeQ[lima, DirectedInfinity] && !FreeQ[limb, DirectedInfinity]))
- ] /; !(TrueQ[a==1] && TrueQ[b==0])
-
- Limit[a_. DiracDelta[f__] + b_., x_ -> c_, dir___] :=
- Module[{lima, limb, limdelta},
- If[limdelta == 0 && !FreeQ[lima, DirectedInfinity],
- limb,
- lima limdelta + limb] /;
- (FreeQ[{lima, limb, limdelta} =
- Limit[{a, b, DiracDelta[f]}, x->c, dir], Limit] &&
- !(limdelta != 0 &&
- !FreeQ[lima, DirectedInfinity] && !FreeQ[limb, DirectedInfinity]))
- ] /; !(TrueQ[a==1] && TrueQ[b==0])
-
- Limit[a_. UnitStep[f__?RuleFreeQ, zero___Rule] + b_., x_ -> c_, dir___] :=
- Module[{lima, limb, limunit},
- If[limunit == 0 && FreeQ[lima, Limit] &&
- !FreeQ[lima, DirectedInfinity],
- limb,
- lima limunit + limb] /;
- ({lima, limb} = Limit[{a, b}, x->c, dir];
- FreeQ[limunit = Limit[UnitStep[f, zero], x->c, dir], Limit] &&
- !(limunit != 0 && FreeQ[{lima, limb}, Limit] &&
- !FreeQ[lima, DirectedInfinity] && !FreeQ[limb, DirectedInfinity]))
- ] /; !(TrueQ[a==1] && TrueQ[b==0])
-
-
- Off[Sum::itform]
- Limit[Sum[a_. Derivative[n__Integer?NonNegative][DiracDelta][f__] + b_., i__],
- x_ -> c_, dir___] :=
- Module[{lima, limb, limdeltader},
- If[limdeltader == 0 && !FreeQ[lima, DirectedInfinity],
- Sum[limb, i],
- Sum[lima limdeltader + limb, i]] /;
- (FreeQ[{lima, limb, limdeltader} =
- Limit[{a, b, Derivative[n][DiracDelta][f]}, x->c, dir], Limit] &&
- !(limdeltader != 0 &&
- !FreeQ[lima, DirectedInfinity] && !FreeQ[limb, DirectedInfinity]))
- ] /; FreeQ[{i}, x]
-
- Limit[Sum[a_. DiracDelta[f__] + b_., i__], x_ -> c_, dir___] :=
- Module[{lima, limb, limdelta},
- If[limdelta == 0 && !FreeQ[lima, DirectedInfinity],
- Sum[limb, i],
- Sum[lima limdelta + limb, i]] /;
- (FreeQ[{lima, limb, limdelta} =
- Limit[{a, b, DiracDelta[f]}, x->c, dir], Limit] &&
- !(limdelta != 0 &&
- !FreeQ[lima, DirectedInfinity] && !FreeQ[limb, DirectedInfinity]))
- ] /; FreeQ[{i}, x]
-
- Limit[Sum[a_. UnitStep[f__?RuleFreeQ, zero___Rule] + b_., i__],
- x_ -> c_, dir___] :=
- Module[{lima, limb, limunit},
- If[limunit == 0 && FreeQ[lima, Limit] &&
- !FreeQ[lima, DirectedInfinity],
- Sum[limb, i],
- Sum[lima limunit + limb, i]] /;
- ({lima, limb} = Limit[{a, b}, x->c, dir];
- FreeQ[limunit = Limit[UnitStep[f, zero], x->c, dir], Limit] &&
- !(limunit != 0 && FreeQ[{lima, limb}, Limit] &&
- !FreeQ[lima, DirectedInfinity] && !FreeQ[limb, DirectedInfinity]))
- ] /; FreeQ[{i}, x]
-
- Limit[a_. sum_?((Head[#] === Sum)&) + b_., x_ -> c_, dir___] :=
- Module[{lima, limb, limsum},
- If[limsum == 0 && FreeQ[lima, Limit] &&
- !FreeQ[lima, DirectedInfinity],
- limb,
- lima limsum + limb] /;
- ({lima, limb} = Limit[{a, b}, x->c, dir];
- FreeQ[limsum = Limit[sum, x->c, dir], Limit] &&
- !(limsum != 0 && FreeQ[{lima, limb}, Limit] &&
- !FreeQ[lima, DirectedInfinity] && !FreeQ[limb, DirectedInfinity]))
- ] /; !(FreeQ[sum, UnitStep] && FreeQ[sum, DiracDelta])
- On[Sum::itform]
-
-
- (********************** limits, UnitStep' and DiracDelta **********************)
-
- Limit[Derivative[n__Integer?NonNegative][DiracDelta][f__],
- x_ -> c_, dir___Rule] :=
- Module[{limit},
- If[Apply[And, Map[NumberQ[N[#]]&, limit]],
- 0, Apply[Derivative[n][DiracDelta], limit]
- ] /; FreeQ[limit = Limit[{f}, x->c, dir], Limit]
- ]
-
- Protect[Limit]
-
- DiracDelta /: Limit[DiracDelta[f__], x_ -> c_, dir___Rule] :=
- Module[{limit},
- If[Apply[And, Map[NumberQ[N[#]]&, limit]],
- 0, Apply[DiracDelta, limit]
- ] /; FreeQ[limit = Limit[{f}, x->c, dir], Limit]
- ]
-
- (****************************** limits, UnitStep ******************************)
-
- (* Default Limit Direction is Automatic. *)
-
- UnitStep /: Limit[UnitStep[f__?RuleFreeQ, zero___Rule], x_ -> c_] :=
- Module[{limit},
- limit /; FreeQ[limit = Limit[UnitStep[f, zero], x -> c,
- Direction -> Automatic], Limit]
- ]
-
- (* For each of UnitStep's arguments that approach an expression not equal to
- zero, take the Limit inside of the UnitStep. *)
-
- UnitStep /: Limit[UnitStep[f__?RuleFreeQ, zero___Rule],
- x_ -> c_, dir___Rule] :=
- Module[{limit = Limit[{f}, x -> c, dir], newf},
- Limit[ UnitStep @@ Join[newf, {zero}], x -> c, dir]
- /; (newf = Map[If[!FreeQ[#[[2]], Limit] || TrueQ[#[[2]]==0],
- #[[1]], #[[2]]]&,
- Transpose[{{f}, limit}]];
- !SameQ[{f}, newf])
- ]
-
- (* If even one of UnitStep's arguments approaches a negative number, then
- UnitStep is zero. *)
-
- UnitStep /: Limit[UnitStep[f__?RuleFreeQ, ___Rule],
- x_ -> c_, dir___Rule] :=
- Module[{limit = Limit[{f}, x -> c, dir]},
- 0 /; Apply[Or, Negative[limit]]
- ]
-
- (* In cases where one or more of UnitStep's arguments approach zero, check
- the derivative of those arguments before deciding what the limit
- should be. There are four cases in where one or more of UnitStep's
- arguments approach zero... *)
-
- UnitStep /: Limit[UnitStep[f__?RuleFreeQ, ___Rule],
- x_ -> c_, Direction -> dir_] :=
- Module[{limit = Limit[{f}, x -> c, Direction -> dir]},
- 1 /; Apply[And, MapIndexed[(Positive[#1] ||
- (#1==0 && IncreasingQ[{f}[[#2[[1]]]], x, c, dir]))&,
- limit]]
- ] /; (dir === Automatic || Negative[dir])
-
- UnitStep /: Limit[UnitStep[f__?RuleFreeQ, ___Rule],
- x_ -> c_, Direction -> dir_] :=
- Module[{limit = Limit[{f}, x -> c, Direction -> dir]},
- 0 /; Apply[Or, MapIndexed[(Negative[#1] ||
- (#1==0 && DecreasingQ[{f}[[#2[[1]]]], x, c, dir]))&,
- limit]]
- ] /; (dir === Automatic || Negative[dir])
-
- UnitStep /: Limit[UnitStep[f__?RuleFreeQ, ___Rule], x_ -> c_,
- Direction -> dir_?Positive] :=
- Module[{limit = Limit[{f}, x -> c, Direction -> dir]},
- 1 /; Apply[And, MapIndexed[(Positive[#1] ||
- (#1==0 && DecreasingQ[{f}[[#2[[1]]]], x, c, dir]))&,
- limit]]
- ]
-
- UnitStep /: Limit[UnitStep[f__?RuleFreeQ, ___Rule], x_ -> c_,
- Direction -> dir_?Positive] :=
- Module[{limit = Limit[{f}, x -> c, Direction -> dir]},
- 0 /; Apply[Or, MapIndexed[(Negative[#1] ||
- (#1==0 && IncreasingQ[{f}[[#2[[1]]]], x, c, dir]))&,
- limit]]
- ]
-
- (* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *)
-
- IncreasingQ[f_, x_, c_, dir_] := Module[{g = D[f, x]},
- If[!FreeQ[g, Derivative] || g == 0, Return[False]];
- While[ TrueQ[Limit[g, x->c, Direction -> dir] == 0],
- g = D[g, x];
- If[!FreeQ[g, Derivative] || g == 0, Return[False]]
- ];
- TrueQ[Positive[Limit[g, x->c, Direction -> dir]]] ]
-
- DecreasingQ[f_, x_, c_, dir_] := Module[{g = D[f, x]},
- If[!FreeQ[g, Derivative] || g == 0, Return[False]];
- While[ TrueQ[Limit[g, x->c, Direction -> dir] == 0],
- g = D[g, x];
- If[!FreeQ[g, Derivative] || g == 0, Return[False]]
- ];
- TrueQ[Negative[Limit[g, x->c, Direction -> dir]]] ]
-
-
- (****************************** Derivatives ***********************************)
-
- Unprotect[Derivative]
-
- Literal[Derivative[n__?NonNegative][UnitStep][x__?RuleFreeQ]] :=
- Module[{l = Transpose[{{n}, {x}}], nonzero, zero, u, d},
- nonzero = Select[l, #[[1]] != 0&]; zero = Complement[l, nonzero];
- u = If[zero === {}, 1, UnitStep @@ Map[#[[2]]&, zero]];
- d = If[nonzero === {}, 1,
- ((Derivative @@ Map[#[[1]]&, nonzero]-1) @@ DiracDelta) @@
- Map[#[[2]]&, nonzero]];
- u * d
- ] /; Length[{n}] == Length[{x}]
-
- Literal[Derivative[n__][UnitStep][x__?RuleFreeQ, r_Rule]] :=
- Module[{l = Transpose[{Drop[{n}, -1], {x}}], nonzero, zero, u, d},
- nonzero = Select[l, #[[1]] != 0&]; zero = Complement[l, nonzero];
- u = If[zero === {}, 1, UnitStep @@ Join[Map[#[[2]]&, zero], {r}]];
- d = If[nonzero === {}, 1,
- ((Derivative @@ Map[#[[1]]&, nonzero]-1) @@ DiracDelta) @@
- Map[#[[2]]&, nonzero]];
- u * d
- ] /; Length[{n}]-1 == Length[{x}] && Apply[And, NonNegative[Drop[{n}, -1]]] &&
- Last[{n}] == 0
-
- Protect[Derivative]
- Unprotect[D]
-
- (* D rules for UnitStep with ZeroValue option *)
-
- Literal[D[a_. UnitStep[f__?RuleFreeQ, r_Rule] + b_.,
- x__?((Head[#] === Symbol || MatchQ[#, {_Symbol, _Integer}])&)]] :=
- D[a UnitStep[f] + b, x] //. ZeroValueRules[r]
-
- (* D rules for Derivative[n__][UnitStep] with ZeroValue option *)
-
- Literal[D[a_. Derivative[m__Integer?NonNegative][UnitStep][f__?RuleFreeQ,
- r_Rule] + b_.,
- x__?((Head[#] === Symbol || MatchQ[#, {_Symbol, _Integer}])&)]] :=
- D[a Apply[Derivative, Drop[{m}, -1]][UnitStep][f] + b, x] //.
- ZeroValueRules[r]
-
- Protect[D]
-
- ZeroValueRules[r_] := {Derivative[n__][UnitStep][g__?RuleFreeQ] :>
- Derivative[n, 0][UnitStep][g, r],
- UnitStep[g__?RuleFreeQ] :> UnitStep[g, r]}
-
- (**************************** integrals, linearity ****************************)
-
- (* Note that Integrate[g[x] v[x] + h[x] v[x], x] ->
- Integrate[(g[x] + h[x]) v[x], x] is built-in to Mathematica. *)
-
- Unprotect[Integrate]
-
- Integrate[f_, x_] :=
- Module[{result},
- Integrate[result, x] /;
- (result = Collect[f, Union[Cases[{f}, UnitStep[__], Infinity],
- Cases[{f}, DiracDelta[__], Infinity],
- Cases[{f}, Derivative[__][DiracDelta][__], Infinity]]];
- !SameQ[f, result])
- ] /; !(FreeQ[f, UnitStep] && FreeQ[f, DiracDelta])
-
- Integrate[c1_. UnitStep[y1__?RuleFreeQ, r1___Rule] + c2_, x_] :=
- Module[{i1},
- SimplifyUnitStep[ i1 + Integrate[c2, x] ] /;
- Head[i1 = Integrate[c1 UnitStep[y1, r1], x]] =!= Integrate ||
- Apply[List, i1] =!= {c1 UnitStep[y1, r1], x}
- ]
-
- Integrate[c1_. DiracDelta[y1__] + c2_, x_] :=
- Module[{i1},
- SimplifyUnitStep[ i1 + Integrate[c2, x] ] /;
- Head[i1 = Integrate[c1 DiracDelta[y1], x]] =!= Integrate ||
- Apply[List, i1] =!= {c1 DiracDelta[y1], x}
- ]
-
- Integrate[a_ UnitStep[y_, r___Rule], x_Symbol] :=
- a Integrate[UnitStep[y, r], x] /; FreeQ[a, x]
-
- Integrate[a_ f_ UnitStep[y_, r___Rule], x_Symbol] :=
- a Integrate[f UnitStep[y, r], x] /; FreeQ[a, x] && !FreeQ[f, x]
-
- Off[Sum::itform]
- Integrate[a_. Sum[f_, i__] + b_., x_Symbol] :=
- Module[{result = Module[{head, F},
- head = Head[F = Integrate[a f, x]];
- If[head =!= Integrate,
- Sum[F, i] + Integrate[b, x],
- $Failed]]},
- result /; result =!= $Failed
- ] /; !(FreeQ[f, DiracDelta] && FreeQ[f, UnitStep]) && FreeQ[{i}, x] &&
- !FreeQ[f, x]
- On[Sum::itform]
-
-
- (**************************** multiple integrals ****************************)
-
- (* Use UnitStep to trim integration limits. *)
-
- Integrate[f_ UnitStep[y__?RuleFreeQ, r___Rule]^(n_.) + g_., z__List] :=
- Module[{x, a, b, na, nb, nc, f2, t, newz, newf =
- (f UnitStep[y, r]^n // SimplifyUnitStep) /. ToUniRules},
- ( newz =
- Map[({x, a, b} = #; {na, nb} = N[{a, b}];
- While[MatchQ[newf,
- f1_ UnitStep[c1_. x + d1_., ___Rule]^(m_.) /;
- (NumberQ[N[c1]] && NumberQ[N[d1]] &&
- ({nc, t, f2} = {N[c1], -d1/c1, f1};
- If[nc > 0, N[t] > na, N[t] < nb]))],
- If[nc > 0,
- If[nb <= N[t], newf = 0,
- newf = f2; a = t; na = N[a]],
- If[na >= N[t], newf = 0,
- newf = f2; b = t; nb = N[b]]]
- ];
- {x, a, b})&,
- {z}];
- Apply[Integrate, Join[{newf}, newz]] + Integrate[g, z] ) /;
-
- Apply[Or, Map[
- ( MatchQ[#, {x1_Symbol, a1_, b1_} /;
- ( {x, a, b} = {x1, a1, b1};
- (NumberQ[N[a]] || Head[a] === DirectedInfinity) &&
- (NumberQ[N[b]] || Head[b] === DirectedInfinity) ) ] &&
- MemberQ[{y}, c_. x + d_. /;
- ( NumberQ[N[c]] && NumberQ[N[d]] &&
- (t = -d/c; If[N[c] > 0, N[t] > N[a], N[t] < N[b]]) ) ] )&,
- {z}]]
-
- ]
-
- (* Eliminate UnitStep terms that are unity. *)
-
- Integrate[f_ UnitStep[y__?RuleFreeQ, r___Rule]^(n_.) + g_., z__List] :=
- Module[{x, a, b, unit, newunit = UnitStep[y, r]^n},
- Scan[({x, a, b} = #;
- If[(unit = (newunit //. {x -> a})) === (newunit //. {x -> b}),
- newunit = unit])&,
- {z}];
- Integrate[f newunit + g, z] /;
-
- Apply[Or, Map[
- ( MatchQ[#, {x1_Symbol, a1_, b1_} /;
- ( {x, a, b} = {x1, a1, b1};
- (NumberQ[N[a]] || Head[a] === DirectedInfinity) &&
- (NumberQ[N[b]] || Head[b] === DirectedInfinity) ) ] &&
- !FreeQ[{y}, x] &&
- ((UnitStep[y, r]^n) //. {x -> a}) ===
- ((UnitStep[y, r]^n) //. {x -> b}) )&,
- {z}]]
- ]
-
- (* Expand if it appears that the UnitStep will allow the
- integration limits to be trimmed. *)
-
- Integrate[f_ (UnitStep[y__?RuleFreeQ, r___Rule]^(n_.) + h_) + g_., z__List] :=
- Module[{x, a, b, t},
- Integrate[Expand[f (UnitStep[y, r]^n + h)] + g, z] /;
-
- Apply[Or, Map[
- ( MatchQ[#, {x1_Symbol, a1_, b1_} /;
- ( {x, a, b} = {x1, a1, b1};
- (NumberQ[N[a]] || Head[a] === DirectedInfinity) &&
- (NumberQ[N[b]] || Head[b] === DirectedInfinity) ) ] &&
- MemberQ[{y}, c_. x + d_. /;
- ( NumberQ[N[c]] && NumberQ[N[d]] &&
- (t = -d/c; If[N[c] > 0, N[t] > N[a], N[t] < N[b]]) ) ] )&,
- {z}]]
-
- ]
-
-
- (* Nest multiple integrals. *)
-
- Integrate[f_, iseq__] :=
- Module[{result =
- Module[{integrand = f, scan, head},
- scan = Scan[(head = Head[integrand = Integrate[integrand, #]];
- If[!(head =!= Integrate || integrand[[2]] =!= #),
- Return[$Failed]])&,
- Reverse[{iseq}]];
- If[scan === $Failed, $Failed, integrand]]},
- result /; result =!= $Failed
- ] /; !(FreeQ[f, DiracDelta] && FreeQ[f, UnitStep]) && Length[{iseq}] > 1
-
-
- (***************************** definite integrals *****************************)
-
- Integrate[f_, {x_, a_, b_}] :=
- Module[{F, lima, limb, pos},
- limb - lima /;
- FreeQ[F = Integrate[f, x], Integrate] &&
- FreeQ[{lima = Limit[F, x->a], limb = Limit[F, x->b]}, Limit] &&
- (FreeQ[lima, DirectedInfinity] || FreeQ[limb, DirectedInfinity])
- ] /; !(FreeQ[f, DiracDelta] && FreeQ[f, UnitStep]) && FreeQ[f, Integrate]
-
-
- (**************************** indefinite integrals ****************************)
-
- (* Integral of a univariate step function with linear argument. *)
-
- Integrate[f_. UnitStep[y_, r___Rule]^(_.), x_Symbol] :=
- Module[{F, F0, a, b},
- SimplifyUnitStep[ (F - F0) UnitStep[a x + b, r] ]
- /; MatchQ[Collect[y, x], c_. x + d_. /; FreeQ[{c, d}, x]] &&
- ({b, a} = CoefficientList[y, x];
- DiracDeltaFreeQ[f, {{x -> -b/a}}] &&
- FreeQ[F = Integrate[f, x], Integrate]) &&
- (F0 = Limit[F, x -> -b/a];
- If[!FreeQ[F0, Limit],
- If[MemberQ[Messages[Power], Literal[Power::infy] :> $Off[_]],
- F0 = F /. x -> -b/a,
- Off[Power::infy];
- F0 = F /. x -> -b/a;
- On[Power::infy] ] ];
- FreeQ[F0, DirectedInfinity] && FreeQ[F0, Indeterminate])
- ]
-
-
- (* Integral of a univariate delta function with arbitrary argument. Delta's
- located off the real line contribute 0. *)
-
- Integrate[f_. DiracDelta[y_], x_Symbol] :=
- Module[{solution, select, derivative, fselect},
- Apply[Plus, Map[(UnitStep[x - (x /. #)])&, select] *
- fselect / Abs[derivative] ]
- /; Head[solution = Solve[Map[(# == 0)&, {y}], {x}]] == List &&
- solution =!= {{}} && If[FreeQ[y, x], True, solution =!= {}] &&
- (select = Select[solution, FreeQ[#, Complex]&]; (select === {} ||
- Apply[And, Map[!TrueQ[# == 0]&, (derivative = D[y, x] /. select)]])) &&
- DiracDeltaFreeQ[f, select] && SmoothQ[f, select] &&
- (fselect = Limit[f, Flatten[select]];
- If[!FreeQ[fselect, Limit],
- If[MemberQ[Messages[Power], Literal[Power::infy] :> $Off[_]],
- fselect = f /. select,
- Off[Power::infy];
- fselect = f /. select;
- On[Power::infy] ] ];
- FreeQ[fselect, DirectedInfinity] && FreeQ[fselect, Indeterminate])
- ]
-
-
- (* Integral of a derivative of a univariate delta function with linear
- argument. *)
-
- Integrate[f_. Derivative[n_Integer?Positive][DiracDelta][y_], x_Symbol] :=
- Module[{f0, a, b},
- ( f0 Derivative[n-1][DiracDelta][a x + b] / a -
- (1/a) Integrate[D[f,x] Derivative[n-1][DiracDelta][a x + b], x]
- ) /; MatchQ[Collect[y, x], a1_. x + b1_. /;
- ({a, b} = {a1, b1}; FreeQ[{a1, b1}, x])] &&
- DiracDeltaFreeQ[f, {{x -> -b/a}}] && SmoothQ[f, {{x->-b/a}}] &&
- (f0 = Limit[f, x-> -b/a];
- If[!FreeQ[f0, Limit],
- If[MemberQ[Messages[Power], Literal[Power::infy] :> $Off[_]],
- f0 = f /. x -> -b/a,
- Off[Power::infy];
- f0 = f /. x -> -b/a;
- On[Power::infy] ] ];
- FreeQ[f0, DirectedInfinity] && FreeQ[f0, Indeterminate])
- ]
-
-
- (* Integral of a multivariate step function with linear arguments. *)
-
- Integrate[f_. UnitStep[yseq__?RuleFreeQ, r___Rule]^(_.), x_Symbol] :=
- Module[{ylist, arg},
- Apply[UnitStep, Join[Select[ylist, FreeQ[#, x]&], {r}]] *
- Integrate[f Apply[UnitStep, Join[arg, {r}]], x]
- /; Length[ylist = {yseq}] > 1 &&
- Length[arg = Select[ylist, (!FreeQ[#, x])&]] == 1 &&
- MatchQ[Collect[arg, x], {a_. x + b_.} /; FreeQ[{a, b}, x]]
- ] /; FreeQ[f, Integrate]
-
-
- (* Integral of a multivariate delta function with arbitrary arguments. *)
-
- Integrate[f_. DiracDelta[yseq__], x_Symbol] :=
- Module[{ylist, arg},
- Apply[DiracDelta, Select[ylist, FreeQ[#, x]&]] *
- Integrate[f Apply[DiracDelta, arg], x]
- /; Length[ylist = {yseq}] > 1 &&
- Length[arg = Select[ylist, (!FreeQ[#, x])&]] == 1
- ] /; FreeQ[f, Integrate]
-
-
- (* Integral of a multivariate delta function derivative with arbitrary
- arguments. *)
-
- Integrate[f_. Derivative[n__Integer][DiracDelta][yseq__], x_Symbol] :=
- Module[{ylist, pos},
- Apply[Apply[Derivative, Drop[{n}, pos]] [DiracDelta], Drop[ylist, pos]] *
- Integrate[f Apply[Apply[Derivative, {n}[[pos]]] [DiracDelta],
- ylist[[pos]]], x]
- /; Length[ylist = {yseq}] > 1 &&
- Length[pos = Flatten[Position[ylist, z_ /; !FreeQ[z, x]]]] == 1
- ] /; FreeQ[f, Integrate]
-
- Protect[Integrate]
-
- DiracDeltaFreeQ[f_, solution_List] :=
- !Apply[Or, Map[TrueQ[# == 0]&, Flatten[
- Join[Cases[{f}, DiracDelta[__], Infinity] /. DiracDelta -> List,
- Cases[{f}, Derivative[__][DiracDelta][__], Infinity] /.
- Derivative[__][DiracDelta] -> List] /. solution
- ] ]]
-
- SmoothQ[f_, solution_List] :=
- !Apply[Or, Map[Module[{limleft = Limit[f, #, Direction -> 1],
- limright = Limit[f, #, Direction -> -1]},
- (FreeQ[limleft, Limit] || FreeQ[limright, Limit]) &&
- limleft =!= limright]&,
- solution]]
-
- SimplifyDiracDelta[expr_] :=
- ( expr //. { f_ DiracDelta[___, a_. y_Symbol + b_.] :> 0 /;
- (0 == (f /. y -> -b/a)) } ) /;
- MemberQ[Messages[Power], Literal[Power::infy] :> $Off[_]]
-
- SimplifyDiracDelta[expr_] :=
- Module[{new},
- Off[Power::infy];
- new = expr //. { f_ DiracDelta[___, a_. y_Symbol + b_.] :> 0 /;
- (0 == (f /. y -> -b/a)) };
- On[Power::infy];
- new
- ] /; !MemberQ[Messages[Power], Literal[Power::infy] :> $Off[_]]
-
- SimplifyDiracDelta[expr_] := expr /; FreeQ[expr, DiracDelta]
-
- SimplifyUnitStep[expr_] :=
- Module[{result =
- Module[{new = expr //. ToUniRules, original = Length[cases[expr]],
- convertTomulti},
- convertTomulti = original < Length[cases[new]];
- new = Expand[new] //. UnitStepRules;
- new = Collect[new, Union[cases[new]]];
- If[convertTomulti, new = new //. ToMultiRules];
- If[original < Length[cases[new]], expr, new]
- ]},
- result
- ] /; !(FreeQ[expr, UnitStep] && FreeQ[expr, DiracDelta])
-
- SimplifyUnitStep[expr_] := expr /; FreeQ[expr, UnitStep] &&
- FreeQ[expr, DiracDelta]
-
- cases[expr_] := Join[Cases[{expr}, UnitStep[__], Infinity],
- Cases[{expr}, DiracDelta[__], Infinity],
- Cases[{expr}, Derivative[__][DiracDelta][__], Infinity]]
-
-
- UnitStepRules = {UnitStep[c1_. x_Symbol + d1_., r1___Rule] *
- UnitStep[c2_. x_ + d2_., r2___Rule] :>
- Module[{t1 = N[d1/c1], t2 = N[d2/c2]},
- If[N[c1] > 0 ,
- If[t1 > t2, UnitStep[c2 x + d2, r2],
- UnitStep[c1 x + d1, r1]],
- If[t1 > t2, UnitStep[c1 x + d1, r1],
- UnitStep[c2 x + d2, r2]]
- ]] /; Apply[And, Map[NumberQ, N[{c1, c2, d1, d2}]]] &&
- N[d2/c2] != N[d1/c1] && Sign[c1] == Sign[c2],
- UnitStep[c1_. x_Symbol + d1_., r1___Rule] *
- UnitStep[c2_. x_ + d2_., r2___Rule] :> 0 /;
- Apply[And, Map[NumberQ, N[{c1, c2, d1, d2}]]] &&
- N[d2/c2] != N[d1/c1] && Sign[c1] != Sign[c2] &&
- ((N[c1] > 0 && N[d1/c1] < N[d2/c2]) ||
- (N[c2] > 0 && N[d2/c2] < N[d1/c1])),
- UnitStep[c1_. x_Symbol + d1_., r___Rule] *
- DiracDelta[c2_. x_ + d2_.] :>
- If[(N[c1] > 0 && N[d2/c2] < N[d1/c1]) ||
- (N[c1] < 0 && N[d2/c2] > N[d1/c1]),
- DiracDelta[c2 x + d2], 0] /;
- Apply[And, Map[NumberQ, N[{c1, c2, d1, d2}]]] &&
- N[d2/c2] != N[d1/c1],
- UnitStep[c1_. x_Symbol + d1_., r___Rule] *
- Derivative[n_Integer?Positive][DiracDelta][c2_. x_ + d2_.] :>
- If[(N[c1] > 0 && N[d2/c2] < N[d1/c1]) ||
- (N[c1] < 0 && N[d2/c2] > N[d1/c1]),
- Derivative[n][DiracDelta][c2 x + d2], 0] /;
- Apply[And, Map[NumberQ, N[{c1, c2, d1, d2}]]] &&
- N[d2/c2] != N[d1/c1],
- c_. UnitStep[a_. x_ + b_., r1___Rule] +
- d_. UnitStep[a_. x_ + b_., r2_Rule] :>
- Module[{k1, k2, k},
- ((c+d) If[SameQ[k, ZeroValue /. Options[UnitStep]],
- UnitStep[a x + b],
- UnitStep[a x + b, ZeroValue -> k]]
- ) /; !SameQ[k1 = ZeroValue /. {r1} /. Options[UnitStep],
- k2 = ZeroValue /. r2] &&
- !TrueQ[N[c + d /. x->-b/a] == 0] &&
- NumberQ[N[k = (k1 c + k2 d)/(c+d) /. x->-b/a]]
- ] /; !SameQ[{r1}, {r2}],
- c_. UnitStep[a_. x_ + b_., r1___Rule] +
- d_. UnitStep[a_. x_ + b_., r2_Rule] :>
- (c+d) UnitStep[a x + b] /; !SameQ[{r1}, {r2}] &&
- SameQ[ZeroValue /. {r1} /. Options[UnitStep],
- ZeroValue /. r2]
- }
-
- ToUniRules = {UnitStep[x__?RuleFreeQ, r___Rule] :>
- Apply[Times, Map[UnitStep[#, r]&, {x}]] /; Length[{x}] > 1,
- DiracDelta[x__] :>
- Apply[Times, Map[DiracDelta, {x}]] /; Length[{x}] > 1,
- Derivative[n__][DiracDelta][x__] :>
- Apply[Times, Map[Derivative[#[[1]]][DiracDelta][#[[2]]]&,
- Transpose[{{n}, {x}}] ]] /; Length[{x}] > 1}
-
- ToMultiRules = {UnitStep[x__?RuleFreeQ, r___Rule] *
- UnitStep[y__?RuleFreeQ, r___Rule] :>
- Apply[UnitStep, Join[{x}, {y}, {r}]],
- DiracDelta[x__] * DiracDelta[y__] :>
- Apply[DiracDelta, Join[{x}, {y}]],
- Derivative[m__][DiracDelta][x__] *
- Derivative[n__][DiracDelta][y__] :>
- Apply[Apply[Derivative, Join[{m}, {n}]][DiracDelta],
- Join[{x}, {y}]],
- UnitStep[x_?RuleFreeQ, r___Rule]^n_Integer?Positive :>
- Apply[UnitStep[#, r]&, Table[x, {n}]],
- DiracDelta[x_]^n_Integer?Positive :>
- Apply[DiracDelta, Table[x, {n}]],
- (Derivative[m_][DiracDelta][x_])^n_Integer?Positive :>
- Apply[Apply[Derivative, Table[m, {n}]][DiracDelta],
- Table[x, {n}]]}
-
- RuleFreeQ[expr_] := FreeQ[expr, Rule]
-
- (* zero distribution, Abs', and simplifying the sign of the arg of DiracDelta
- or Derivative[_][DiracDelta] *)
-
- DiracDelta /: (y_)^n_. DiracDelta[___, y_] := 0 /; IntegerQ[n] && n > 0
-
- DiracDelta /: UnitStep[z__?RuleFreeQ, r___Rule] *
- DiracDelta[x___, a_. y_Symbol + b_.] :=
- Module[{k = UnitStep[z, r] /. y -> -b/a},
- k DiracDelta[x, a y + b]
- ] /; !FreeQ[{z}, y] && NumberQ[N[a]] && NumberQ[N[b]]
-
- DiracDelta[a_ b_., y___] := DiracDelta[Abs[a] b, y] /; Negative[N[a]]
- DiracDelta[x_Plus, y___] :=
- DiracDelta[ Apply[Plus, Map[(-#)&, Apply[List, x] ]] ] /;
- Apply[And, Map[MatchQ[#, a_ b_. /; Negative[N[a]]]&, Apply[List, x] ]]
-
- Unprotect[Derivative]
- Derivative /: (y_)^m_Integer?Positive *
- Derivative[n__Integer?NonNegative][DiracDelta][x1___, y_, x2___] :=
- 0 /; Length[{n}] == Length[{x1, y, x2}] && m > {n}[[ Length[{x1}] + 1 ]]
-
- Derivative /: y_ Derivative[1][Abs][y_] := Abs[y]
-
- Derivative[n__Integer?NonNegative][DiracDelta][y1___, a_ b_., y2___] :=
- (-1)^({n}[[ Length[{y1}] + 1 ]]) *
- Derivative[n][DiracDelta][y1, Abs[a] b, y2] /; Negative[N[a]] &&
- Length[{n}] == Length[{y1, a b, y2}]
-
- Derivative[n__Integer?NonNegative][DiracDelta][y1___, x_, y2___] :=
- (-1)^({n}[[ Length[{y1}] + 1 ]]) *
- Apply[ Derivative[n][DiracDelta],
- Join[{y1},
- {Apply[Plus, Map[(-#)&, Apply[List, x] ]]},
- {y2}] ] /;
- Apply[And, Map[MatchQ[#, a_ b_. /; Negative[N[a]]]&, Apply[List, x] ]] &&
- Length[{n}] == Length[{y1, a b, y2}]
- Protect[Derivative]
-
- (*****************************************************************************)
-
- Protect[UnitStep, DiracDelta]
-
- End[]
-
- EndPackage[]
-
-
-
-