(*  :Title:	Forward Laplace Transform Package  *)

(*  :Authors:	Brian Evans, James McClellan  *)

(*  :Summary:	*)

(*  :Context:	SignalProcessing`Analog`LaPlace`  *)

(*  :PackageVersion:  2.6	*)

(*
    :Copyright:	Copyright 1990-1991 by Brian L. Evans
		Georgia Tech Research Corporation

	Permission to use, copy, modify, and distribute this software
	and its documentation for any purpose and without fee is
	hereby granted, provided that the above copyright notice
	appear in all copies and that both that copyright notice and
	this permission notice appear in supporting documentation,
	and that the name of the Georgia Tech Research Corporation,
	Georgia Tech, or Georgia Institute of Technology not be used
	in advertising or publicity pertaining to distribution of the
	software without specific, written prior permission.  Georgia
	Tech makes no representations about the suitability of this
	software for any purpose.  It is provided "as is" without
	express or implied warranty.
 *)

(*
   :History:	began --  February, 1990 (adapted from "ZTransform.m")
		added Dialogue ability --  February, 1991
*)

(*  :Keywords:	*)

(*
    :Source:	Muth, E. J.  {Transform Methods}.  1977.
		Franklin, G. F. {Feedback Control of Dynamic Systems}. 1986.
		Bracewell. {The Fourier Transform and Its Applications}. 1978.
		Nilsson, J. W. {Electric Circuits}
		Churchill, R. {Operational Mathematics}. 1958.
		Oberhettinger, F., and Badii, L.  {Tables of Laplace
			Transforms}, 1973.
 *)

(*
    :Warning:	Keep conditional clauses (code following /;) on the same line;
		  breaking a clause into lines separated by RETURNS will
		  confuse Mathematica (e.g., the active context for this
		  package will not be reset to Global).
 *)

(*  :Mathematica Version:  1.2 or 2.0  *)

(*  :Limitation:  *)

(*
    :Discussion:  All new functions have usage information.
		  The 1-D rule base has a total of 102 rules:

		    I.   multidimensional hooks		  3 rules
		    II.  rational transform pairs	 13 rules
		    III. non-rational transform pairs	 40 rules
		    IV.  transform properties		 23 rules *
		    V.   transforms of SP structures	 14 rules **
		    VI.  transform strategies		  9 rules

		  *  one rule has been commented out
		  ** two rules have been commented out

	The only purpose to the multidimensional hook rules is to track
	the region of convergence for non-separable functions.  Without
	these rules, the  z-transform  rule  base  would still properly
	compute the z-transform function.   Otherwise, the CTFTransform
	would  not  work  properly  for functions  like  Exp[-(6/7)^t1]
	Exp[-(9/10)^t2] Delta[t1 - t2] CStep[t1, t2]  with  respect  to
	variables t1 and t2.

	At each  step  in the Laplace rule base, the current expression
	has a local state associated with it.  This  state  consists of
	a list of six boolean values.  Each boolean value is associated
	with a strategy.  If an element is True, then that strategy has
	not been tried yet;  if False,  then  that strategy has already
	been tried, and it will not be tried again.   Thus, local state
	is used to prevent infinite loops  which would be caused by the
	repetitive application  of  certain  strategy  rules.   See the
	section  S T A T E    D E F I N I T I O N  below and section VI
	of the rules.

	MyLaPlace[ f[t], t, s, state, tlist, slist ] is one-dimensional
	Laplace transform rule base.   It returns the transform of f[t]
	as a three-element list:  { F(s), Rminus, Rplus }.   The "time"
	variable being  transform  is t, and s is the Laplace variable.
	The  complete  collection  of  time  variables  is in tlist and
	Laplace variables in slist.   Note that LaPlace drives the rule
	base defined by MyLaPlace  when  computing  the forward LaPlace
	transform.
 *)

(*  :Functions:  LaPlace  *)


If [ TrueQ[ $VersionNumber >= 2.0 ],
     Off[ General::spell ];
     Off[ General::spell1 ] ];


(*  B E G I N     P A C K A G E  *)

BeginPackage[ "SignalProcessing`Analog`LaPlace`",
	      "SignalProcessing`Analog`LSupport`",
	      "SignalProcessing`Support`TransSupport`",
	      "SignalProcessing`Support`ROC`",
	      "SignalProcessing`Support`SigProc`",
	      "SignalProcessing`Support`SupCode`",
	      "SignalProcessing`Support`FilterSupport`" ]


(*  U S A G E     I N F O R M A T I O N  *)

LaPlace::usage =
	"LaPlace[e, t] or LaPlace[e, t, s] gives the two-sided Laplace \
	transform of the expression e, which is a function of t, by \
	returning an object of four slots tagged by LTransData: \
	<transform>, <rminus>, <rplus>, <laplace_variables>. \
	The Region of Convergence (ROC) is defined as \
	<rminus> < Re{s} < <rplus>. \
	Note that the returned ROC is either the actual ROC or a subset \
	of the actual ROC. \
	In two dimensions, LaPlace[e, {t1, t2}, {s1, s2}] \
	is the same as LaPlace [ LaPlace[e, t1, s1], t2, s2 ]. \
	This notation extends naturally to higher dimensions. \
	Note that the right-sided transform is specified by \
	multiplying the expression by CStep[t]. \
	Also, LaPlaceTransform is an alias for LaPlace."

(*  E N D     U S A G E     I N F O R M A T I O N  *)


Begin["`Private`"]


(*  U S E R     I N T E R F A C E  *)

(*  L operator  *)
Unprotect[L]
L/: TheFunction[ L[t_, s_][f_] ] := LaPlace[f, t, s]
Protect[L]

(*  LaPlace  *)
LaPlace/: Options[ LaPlace ] :=
	{ Definition -> False, Dialogue -> True,
	  Simplify -> True, TransformLookup -> {} }

LaPlace[e_] :=
	laplacedriver[ Options[LaPlace], e ]
LaPlace[e_, t_] :=
	laplacedriver[ Options[LaPlace], e, t ]
LaPlace[e_, t_, s_] :=
	laplacedriver[ Options[LaPlace], e, t, s ]
LaPlace[e_, t_, s_, op__] :=
	laplacedriver[ ToList[op] ~Join~ Options[LaPlace], e, t, s ]

(*  Interface support for LaPlace  *)
laplacedriver[op_, f_, args__] :=
	cleanup [ laplace[op, ToContinuous[f], args],
		  Replace[Dialogue, op],
		  TrueQ[Replace[Simplify, op]] ]

laplace[op_, f_, args___] :=
	Block [	{},
		Replace [ ltrans[op, f, args], LaPlaceInterfaceRules ] ]

LaPlaceInterfaceRules = {
	ltrans[op_, e_] :>
		Message[Transform::novariables, "t (time)", GetVariables[e]],

	ltrans[op_, e_, t_] :> e	/; LTransformQ[e],
	ltrans[op_, e_, t_] :>
		laplace[op, e, t, DummyVariables[Length[t], Global`s] ] /;
		validvarQ[t],

	ltrans[op_, e_, t_, rest___] :>
		Message[ Transform::badvar, "time", LaPlace, t ] /;
		! validvarQ[t],
	ltrans[op_, e_, t_, s_, rest___] :>
		Message[ Transform::badvar, "s", LaPlace, s ] /;
		! validvarQ[s],

	ltrans[op_, e_, t_List, sl_] :>
		MultiDTransform[ MakeLObject, laplace,
				 LTransformQ, e, t, s, sl, op ],

	ltrans[op_, e_, t_Symbol, s_Symbol] :>
		laplace[op, e, t, s, {t}, {s}],
	ltrans[op_, e_, t_Symbol, s_Symbol, tlist_, slist_] :>
		If [ SameQ[ToList[LVariables[e]], slist],
		     e,
		     LMultiDROC[laplace[op, TheFunction[e], t, s, tlist, slist],
				e] ] /;
		LTransformQ[e],
	ltrans[op_, e_, t_Symbol, s_Symbol, tlist_, slist_] :>
		MakeLObject [ MyLaPlace [ e, t, s, initLstate[],
					  tlist, slist, op ],
			      s ] /;
		! LTransformQ[e]
}

cleanup[ Null, dialogue_, simplify_ ] := Null

cleanup[trans_, dialogue_, simplify_ ] :=
	Block [	{dialflag, retval},
		retval = trans;
		dialflag = SameQ[dialogue, All];
		If [ simplify,
		     Off[Replace::rep];
		     retval = SPSimplify[trans, Dialogue -> dialflag];
		     On[Replace::rep] ];
		If [ dialogue || dialflag,
		     Scan[explain, retval, Infinity] ];
		retval ]

explain[ mylaplace[ f_, t_, rest__ ] ] :=
	Message[ Transform::incomplete, "forward Laplace transform", f, t ]

validvarQ[ x_Symbol ] := True
validvarQ[ x_List ] := Apply[And, Map[VariableQ, x]]
validvarQ[ x_ ] := False


(*  S U P P O R T I N G     R O U T I N E S    F O R     R U L E     B A S E  *)

absDialogue[f_, t_, options_] :=
	Block [	{dialogue, result},
		dialogue = InformUserQ[ options ];
		result = (f /. Abs[a_. t] :> Abs[a] t) CStep[t] +
			 (f /. Abs[b_. t] :> - Abs[b] t) CStep[-t];

		If [ dialogue,
		     Print[ "( after rewriting the two-sided expression" ];
		     Print[ "  ", f ];
		     Print[ "  as a left-sided plus a right-sided function:"];
		     Print[ "  ", result, " . )" ] ];

		result ]

addL[trans1_, trans2_] := AddT[LForm, trans1, trans2, -Infinity]

antiCausalL[trans_, s_] :=
	Transform[ TheFunction[trans] /. s -> -s,
		   -GetRPlus[trans], -GetRMinus[trans] ] /;
	LForm[trans]

conjL[trans_, s_] := ConjT[LForm, trans, s]

convolveL[convop_, trans1_, trans2_] :=
	ConvolveT[LForm, convop, trans1, trans2]

definitionDialogue[ oldexpr_, trans_, operator_, options_ ] :=
	Block [	{},
		If [ InformUserQ[options],
		     Print[ "( after using ", operator,
			    "  to apply the definition to" ];
		     Print[ "  ", oldexpr ];
		     Print[ "  to find its transform"];
		     Print[ "  ", trans, " )" ] ];
		trans ]

integrateL[trans_, s_] := IntegrateT[LForm, trans, s, s, Infinity]

lDerivative[trans_, s_, m_] := scaleL[DerivativeT[LForm, trans, s, m], (-1)^m]

lineImpulseMDL[trans_, s_, slist_, sleft_] :=
	LineImpulsemDT[LForm, trans, s, slist, sleft, Plus]

lMultiplyByExp[trans_, s_, a_] :=
	Block [	{newrm, newrp, transform},
		newrm = GetRMinus[trans] - Re[a];
		newrp = GetRPlus[trans] - Re[a];
		transform = Transform[ TheFunction[trans], newrm, newrp ];
		substituteForL[transform, s, s+a] ] /;
	LForm[trans]

multL[trans1_, trans2_] := MultT[LForm, trans1, trans2, -Infinity]

scaleL[trans_, c_] := ScaleT[LForm, trans, c]

similarityL[x_, s_, scale_] :=
	Block [	{adjrm, adjrp, newx},
		adjrm = GetRMinus[x];
		If [ ! InfinityQ[adjrm], adjrm *= scale ];
		adjrp = GetRPlus[x];
		If [ ! InfinityQ[adjrp], adjrp *= scale ];
		newx = Transform[ TheFunction[x],
				  Min[adjrm, adjrp],
				  Max[adjrm, adjrp] ];
		scaleL[ substituteForL[ newx, s, s/scale ], 1/Abs[scale] ] ] /;
	LForm[x]

similarityQ[f_, t_] :=
	Block [	{scale},
		scale = ScalingFactor[f, t];
		(! SameQ[scale, 1]) && (! SameQ[scale, 0]) ]

subL[trans1_, trans2_] := SubT[LForm, trans1, trans2, -Infinity]

substituteForL[trans_, s_, news_] := SubstituteForT[LForm, trans, s, news]

summationL[trans_, op_ ] :=
	Block [	{fun, rm, rp},
		fun = TheFunction[trans];
		rm = GetRMinus[trans];
		rp = GetRPlus[trans];
		Transform[ op[fun], rm, rp ] ] /;
	LForm[trans]

(* one-sided function *)
timeDerivative[x_, s_, m_, f_, t_] :=
	Block [	{curderivative, i, result, rm, rp, xfun},
		rm = Max[0, GetRMinus[x]];
		rp = GetRPlus[x];
		xfun = TheFunction[x];

		result = s^m xfun  -  s^(m-1) Limit[f, t -> 0];
		curderivative = f;
		For [ i = 2, i <= m, i++,
		      curderivative = D[curderivative, t];
		      result -= s^(m-i) Limit[curderivative, t -> 0] ];
		Transform[result, rm, rp] ] /;
	LForm[x] && IntegerQ[m]


(*  S T A T E     D E F I N T I O N  *)

(*  In order of appearance in rule base  *)

polyfactorfield = 1		(* factor denominator if denom. is rat. poly  *)
partialfractionsfield = 2	(* partial fractions if denom. is rat. poly.  *)
expandfield = 3			(* apply Expand[] to expression		      *)
expandallfield = 4		(* apply ExpandAll[] to expression	      *)
collectallfield = 5		(* apply Collect to every level of expression *)
stepfield = 6			(* multiply by (CStep[t] + CStep[-t])	      *)
thefunfield = 7			(* apply TheFunction[] to expression	      *)
definitionfield = 8		(* apply definition of Laplace transform      *)

statevariables = 8

initLstate[] := Table[True, {statevariables}]
nullLstate[] := Table[False, {statevariables}]


(*   Driver for one-dimensional rule base			*)
(*   First, convert all z /(z - a) forms to 1/(1 - a z^-1)	*) 
(*	since the rule base favors terms with z^-1 terms	*)
(*   Loop until the expression to be inverted does not change.	*)
(*   Use fixUp to remove the TransformLookup option before	*)
(*	the options are passed on to the rule base; otherwise,	*)
(*	the rule base could loop indefinitely.			*)
MyLaPlace[ f_, t_, s_, st_, tlist_, slist_, op_ ] :=
	Block [ {laste = Null, newe, newf, newlrules, trace},

		(* generate the forward Laplace transform rules *)
		newlrules = TransformFixUp[ t, s, op, mylaplace, True,
					    LaPlace, -Infinity, Infinity ];
		LaPlaceRules = Join[ newlrules, OriginalLaPlaceRules ];

		(* determine the level of dialogue *)
		trace = SameQ[ Replace[Dialogue, op], All ];

		(* separate Sqrt[b t] forms into Sqrt[b] Sqrt[t] forms *)
		newf = f /. ( Sqrt[b_ t] :> Sqrt[b] Sqrt[t] /; FreeQ[b, t] );

		(* take the 1-D Laplace transform *)
		newe = mylaplace[newf, t, s, st, tlist, slist, fixUp[op]];
		While [ ! SameQ[ laste, newe ],
			If [ trace, Print[ newe ]; Print[ "which becomes" ] ];
			laste = newe;
			newe = MapAll[transform, laste] ];
		If [ trace, Print[ newe ] ];

		newe ]

(*  fixUp --  remove redundant options and the option TransformLookup  *)
fixUp[ op_ ] := { Definition -> Replace[Definition, op],
		  Dialogue -> Replace[Dialogue, op],
		  Simplify -> Replace[Simplify, op] }

transform[ expr_ ] :=
	If [ SameQ[Head[expr], mylaplace],
	     Replace [ expr, LaPlaceRules ],
	     expr ]


(* Format intermediate forms so that output from Dialogue -> All is readable *)

Format[ mylaplace[ x_, t_, s_, st_, tlist_, slist_, op_ ] ] := 
	SequenceForm[ ColumnForm[{"L",
				  "  " ~StringJoin~ ToString[t]}],
		      { x } ]

Format[ antiCausalL[trans_, s_] ] :=
	SequenceForm[ {trans}, Subscript[s -> -s], Subscript[" and flip ROC "] ]

Format[ lMultiplyByExp[trans_, s_, a_] ] :=
	SequenceForm[ {trans},
		      Subscript[s -> s + a],
		      Subscript[" and shift ROC "] ]

Format[ similarityL[trans_, s_, scale_] ] :=
	SequenceForm[ {trans},
		      Subscript[s -> s/scale],
		      Subscript[" and scale transform & ROC "] ]

tdfmt = "`` - Summation[i, 0, ``, 1][`` Limit[ D[``, {``, i}], `` -> 0 ] ]"

Format[ timeDerivative[x_, s_, m_, f_, t_] ] :=
	ToString[ StringForm[ tdfmt, s^m x, m - 1, s^(m - "i"), f, t, t ] ]


(*  B E G I N     R U L E     B A S E  *)


LaPlaceRules = {}


OriginalLaPlaceRules = {


(*  I.    M U L T I D I M E N S I O N A L     H O O K S  *)


(*        A.  Region of convergence specification for dimension given	*)
(*		by the variable n.  Allows multi-dimensional LaPlace	*)
(*		transforms like a^t1 Delta[t1 - t2] CStep[t1,t2] to be	*)
(*		taken --  see Line impulses				*)
mylaplace[ SignalProcessing`ROCinfo[t_, rm_:-Infinity , rp_:Infinity], t_, s_,
	   st_, tlist_, slist_, options_ ] :>
	Transform[ 1, rm, rp ],


(*	  B.  Multidimensional line Deltas become LineImpulses.		*)
mylaplace[ f_. Delta[k_. t1_Symbol + l_. t2_Symbol], t_, s_,
	   st_, tlist_, slist_, options_ ] :>
	mylaplace[ f LineImpulse[{t1,t2}, {k,-l}], t, s,
		   st, tlist, slist, options ] /;
	SubsetQ[{t1, t2}, tlist] && MemberQ[{t1, t2}, t],


(*	  C.  Line impulses.						*)
mylaplace[ f_. LineImpulse[varlist_, coefflist_], t_, s_,
	   st_, tlist_, slist_, options_ ] :>
	Block [	{functionoft, slistmD},
		functionoft = f /. ReplaceWith[varlist, t / coefflist];
		slistmD = AssociateItem[varlist, tlist, slist];
		lineImpulseMDL [ mylaplace [ functionoft, t, s,
					     st, tlist, slist, options ],
			         s, slistmD, Complement[varlist,{t}]] ] /;
	FreeQ[f, LineImpulse[a__]],




(*  II.   R A T I O N A L     L A P L A C E     T R A N S F O R M S	*)


(*	  A.  Lookup rules for the zero, step, and impulse functions.	*)
mylaplace[ 0, t_, s_, st_, tlist_, slist_, options_ ] :>
	Transform[ 0, -Infinity, Infinity ],

mylaplace[ CStep[t_], t_, s_, st_, tlist_, slist_, options_ ] :>
	Transform[ 1/s, 0, Infinity ],

mylaplace[ f_. Delta[a_. t_ + t0_.], t_, s_, st_, tlist_, slist_, options_ ] :>
	Transform[ (f /. t -> -t0/a) Exp[s t0/a] / Abs[a],
		    -Infinity, Infinity ] /;
	FreeQ[{a,t0}, t],

mylaplace[ Unit[n_][t_ + t0_.], t_, s_, st_, tlist_, slist_, options_ ] :>
	Transform[ s^n Exp[s t0], -Infinity, Infinity ] /;
	IntegerQ[n] && n > 0 && FreeQ[t0, t],

mylaplace[ t_^n_. CStep[t_], t_, s_, st_, tlist_, slist_, options_ ] :>
	Block [	{dialogue},
		dialogue = SameQ[Replace[Dialogue, options], All];
		Assuming[ n > 0, dialogue ];
		If [ dialogue && ! IntegerQ[n],
		     Print[ "and that ", n, " is an integer" ] ];
		Transform[ n! / s^(n+1), 0, Infinity ] ] /;
	Implies[ NumberQ[n], IntegerQ[n] && n > 0 ],


(*	  B.  Sinusoidal functions --  note that cross terms like	*)
(*		cos(at) cos(bt) are handled by properties		*)
mylaplace[ Sin[b_. + w_. t_] CStep[t_], t_, s_,
	   st_, tlist_, slist_, options_ ] :>
	Transform[ (s Sin[b] + w Cos[b]) / (s^2 + w^2), 0, Infinity ] /;
     FreeQ[{b,w}, t],		     (*  Modified from [Franklin, 591]  *)

mylaplace[ Cos[b_. + w_. t_] CStep[t_], t_, s_,
	   st_, tlist_, slist_, options_ ] :>
	Transform[ (s Cos[b] - w Sin[b]) / (s^2 + w^2), 0, Infinity ] /;
     FreeQ[{b,w}, t],		     (*  Modified from [Franklin, 591]  *)

mylaplace[ a_. Sinh[b_. + w_. t_] CStep[t_], t_, s_,
	   st_, tlist_, slist_, options_ ] :>
	Transform[a (s Sinh[b] + w Cosh[b]) / (s^2 - w^2), Abs[w], Infinity] /;
     FreeQ[{a,b,w}, t],		     (*  Modified from [Franklin, 591]  *)

mylaplace[ a_. Cosh[b_. + w_. t_] CStep[t_], t_, s_,
	   st_, tlist_, slist_, options_ ] :>
	Transform[a (s Cosh[b] - w Sinh[b]) / (s^2 - w^2), Abs[w], Infinity] /;
     FreeQ[{a,b,w}, t],		     (*  Modified from [Franklin, 591]  *)

mylaplace[ Sin[a_. t_]^2 CStep[t_], t_, s_,
	   st_, tlist_, slist_, options_ ] :>
	Transform[ 2 a^2 / ( s (s^2 + 4 a^2) ), 2 Abs[Im[a]], Infinity ] /;
	FreeQ[a, t],			     (*  [O & B, Formula 7.38]  *)

mylaplace[ Cos[a_. t_]^2 CStep[t_], t_, s_, st_, tlist_, slist_, options_ ] :>
	Transform[ (s^2 + 2 a^2)/(s (s^2 + 4 a^2)), 2 Abs[Im[a]], Infinity ] /;
	FreeQ[a, t],			     (*  [O & B, Formula 7.39]  *)

(*	  C.  Constant function						*)
mylaplace[ a_, t_, s_, st_, tlist_, slist_, options_ ] :>
	Transform[ a Delta[s], 0, 0 ] /;
	FreeQ[a, t],

(*	  D.  LaGuerre polynomials					*)
mylaplace[ LaguerreL[n_, t_ + b_.] CStep[t_], t_, s_,
		st_, tlist_, slist_, options_ ] :>
	Transform[ Exp[b s] ((s - 1)/s)^n / s, 0, Infinity ] /;
	FreeQ[{b,n}, t],

(*	  E.  Other rational transform pairs				*)
mylaplace[ t_^j_. BesselJ[j_, a_. t_] CStep[t_], t_, s_,
		st_, tlist_, slist_, options_ ] :>
	Transform[ (2 a)^j Gamma[j + 1/2] / ( Sqrt[Pi] (s^2 + a^2)^(j + 1/2) ),
		   0, Infinity ] /;
	FreeQ[{a,j}, t],




(*  III.  N O N - R A T I O N A L     L A P L A C E     T R A N S F O R M S  *)


(*	  A.  "Time" functions whose denominators are rational polys	*)

(*	      1.  Put functions with rational polynomial denominators	*)
(*		  in standard form (factor denominator, expand numer.)	*)
mylaplace[ p_, t_, s_, st_, tlist_, slist_, options_ ] :>
	mylaplace [ Expand[Numerator[p]] / ( Factor[Denominator[p]] ), t, s,
		    SetStateField[st, polyfactorfield, False],
		    tlist, slist, options ] /;
	GetStateField[st, polyfactorfield] &&
	  PolynomialQ[Denominator[p], t] && RationalFunctionQ[p, t],

(*	      2.  Normalize the factors of the denominator		*)
(*		  a.  for numeric k, numeric j				*)
mylaplace[ ((a_ + b_ t_^j_.)^k_) x_., t_, s_,
		st_, tlist_, slist_, options_ ] :>
	b^k mylaplace[ x ( a/b + t^j )^k, t, s, st, tlist, slist, options ] /;
	FreeQ[{a,b},t] && IntegerQ[k] && (k < 0) && IntegerQ[j] && (j > 0),

(*		  b.  for symbolic k, numeric j				*)
mylaplace[ x_. / ((a_ + b_ t_^j_.)^k_.), t_, s_,
	   st_, tlist_, slist_, options_ ] :>
	b^(- k) mylaplace[x / (a/b + t^j)^k, t, s, st, tlist, slist, options] /;
	FreeQ[{a,b,k},t] && IntegerQ[j] && (j > 0),

(*	      3.  Partial fractions decomposition			*)
mylaplace[ p_, t_, s_, st_, tlist_, slist_, options_ ] :>
	mylaplace [ Apart[p, t], t, s, 
		    SetStateField[st, partialfractionsfield, False],
		    tlist, slist, options ] /;
	GetStateField[st, partialfractionsfield] &&
	  PolynomialQ[Denominator[p], t] && RationalFunctionQ[p, t],

(*	      4.  Denominator sections					*)
mylaplace[ CStep[t_] / ( t_ + a_ ), t_, s_, st_, tlist_, slist_, options_ ] :>
	Transform[ - Exp[a s] ExpIntegralEi[- a s], 0, Infinity ] /;
	FreeQ[a, t],			      (*  [O & B, Formula 2.9]  *)

mylaplace[ CStep[t_] / ( t_ + a_ )^2, t_, s_,
		st_, tlist_, slist_, options_ ] :>
	Transform[ 1 / a + s Exp[a s] ExpIntegralEi[- a s], 0, Infinity ] /;
	FreeQ[a, t],

mylaplace[ CStep[t_] / ( t_^2 + b_ ), t_, s_,
		st_, tlist_, slist_, options_ ] :>
	Block [	{a, trans},
		a = Sqrt[b];
		trans = CosIntegral[a s] Sin[a s] / a -
			SinIntegral[a s] Cos[a s] / a;
		Transform[trans, 0, Infinity] ] /;
	FreeQ[b, t] && Positive[b],	     (*  [O & B, Formula 2.16]  *)

mylaplace[ CStep[t_] / ( t_^2 + b_ ), t_, s_,
		st_, tlist_, slist_, options_ ] :>
	Block [	{g, trans},
		a = Sqrt[- b];
		trans = ExpIntegralEi[- a s] Exp[a s] / ( 2 a ) -
			(I Pi + ExpIntegralEi[a s] Exp[- a s] ) / ( 2 a );
		Transform[trans, 0, Infinity] ] /;
	FreeQ[{a,b}, t] && Negative[b],	     (*  [O & B, Formula 2.21]  *)

mylaplace[ (a_. t_ + b_.) CStep[t_] / (t_^2 + d_), t_, s_,
	   st_, tlist_, slist_, options_ ] :>
	Block [ {c, trans},
		c = Sqrt[d];
		trans = - CosIntegral[c s] (a Cos[c s] - b Sin[c s] / c) -
			SinIntegral[c s] (a Sin[c s] + b Cos[c s] / c);
		Transform[trans, 0, Infinity] ] /;
	FreeQ[{a,b,c,d}, t] && Positive[d],  (*  [O & B, Formula 2.19]  *)

mylaplace[ (a_. t_ + b_.) CStep[t_] / (t_^2 + d_), t_, s_,
	   st_, tlist_, slist_, options_ ] :>
	Block [	{c, trans},
		c = Sqrt[- d];
		trans = - ExpIntegralEi[- c s] Exp[c s] (a - b/c) / (2 f) -
			ExpIntegralEi[c s] Exp[- c s] (a + b/c) / (2 f );
		Transform[trans, 0, Infinity] ] /;
	FreeQ[{a,b,d}, t] && Negative[d],    (*  [O & B, Formula 2.23]  *)

mylaplace[ CStep[t_] / t_, t_, s_, st_, tlist_, slist_, options_ ] :>
	Transform[ - Log[s], 0, Infinity ],	  (*  [Churchill, 324]  *)

mylaplace[ (t_ + b_.)^k_. CStep[t_ + b_.], t_, s_,
		st_, tlist_, slist_, options_ ] :>
	Block [	{},
		Assuming[ Positive[k + 1], options];
		Transform[ Exp[b s] Gamma[k+1] / s^(k+1), 0, Infinity ] ] /;
	FreeQ[b, t] && Implies[NumberQ[N[k]], N[k > -1]],
					      (*  [O & B, Formula 3.3]  *)


(*	  B.  "Time" functions whose denominators contains powers of t	*)

mylaplace[ CPulse[l_, t_ + k_.] / Sqrt[ t_ ( t_ + l_ ) ],
	   t_, s_, st_, tlist_, slist_, options_ ] :>
	Transform[ -I Pi Exp[s k] Exp[l s / 2] BesselI[0, l s / 2],
		    -Infinity, Infinity ] /;
	FreeQ[{k,l}, t],		    (*  [Churchill, 323 & 331]  *)

mylaplace[ t_ CPulse[l_, t_ + k_.] / Sqrt[ t_ ( t_ + l_ ) ], t_, s_,
	   st_, tlist_, slist_, options_ ] :>
	Transform[ I Pi l Exp[s k] Exp[l s / 2] BesselI[0, l s / 2] -
		    I Pi l Exp[l s / 2] BesselI[1, l s / 2],
		    -Infinity, Infinity ] /;
	FreeQ[{k,l}, t],		    (*  [Churchill, 323 & 331]  *)


(*	  C.  Gaussian function						*)
mylaplace[ Exp[a_. t_^2] CStep[t_], t_, s_, st_, tlist_, slist_, options_ ] :>
	Transform[ Sqrt[Pi / -a] Exp[- s^2 / (4 a)] *
		    ( 1 - Erf[s / (2 Sqrt[-a])] ), -Infinity, Infinity ] /;
	FreeQ[a, t],			      (*  [O & B, Formula 5.41] *)


(*	  D.  Common waves						*)

(*	      1.  square waves						*)
mylaplace[ SquareWave[c_, t_] CStep[t_], t_, s_,
	   st_, tlist_, slist_, options_ ] :>
	Transform[Tanh[c s / 2] / s, 0, Infinity] /;
	FreeQ[c, t],				   (*  [Churchill, 54]  *)

(*	      2.  full-wave rectified sinusoids				*)
mylaplace[ Abs[Sin[a_. t_]] CStep[t_], t_, s_,
	   st_, tlist_, slist_, options_ ] :>
	Transform[a Coth[Pi s / (2 a)] / (s^2 + a^2), Abs[Im[a]], Infinity] /;
	FreeQ[a, t],			      (*  [O & B, Formula 7.3]  *)

mylaplace[ Abs[Cos[a_. t_]] CStep[t_], t_, s_,
	   st_, tlist_, slist_, options_ ] :>
	Transform[ ( s + a Csch[Pi s / (2 a)] ) / (s^2 + a^2),
		    Abs[Im[a]], Infinity ] /;
	FreeQ[a, t],			      (*  [O & B, Formula 7.4]  *)


(*	  E.  Bessel functions						*)

(*  Bessel functions [Churchill, 327] and [O & B, Formulas 14.1/15.1]	*)
(*  Note that formula 14.1 in O & B has a typo in it: -v should be v	*)

mylaplace[ BesselI[v_, a_. t_] CStep[t_], t_, s_,
	   st_, tlist_, slist_, options_ ] :>
	Block [	{},
		Assuming[ Positive[Re[v] + 1], options ];
		Transform[ (s - Sqrt[s^2 - a^2])^v / (a^v Sqrt[s^2 - a^2]),
			   Abs[Re[a]], Infinity ] ] /;
	FreeQ[{a,v}, t] && Implies[NumberQ[N[v]], N[Re[v] > -1]],

mylaplace[ BesselJ[v_, a_. t_] CStep[t_], t_, s_,
	   st_, tlist_, slist_, options_ ] :>
	Block [	{},
		Assuming[ Positive[Re[v] + 1], options];
		Transform[ (Sqrt[s^2 + a^2] - s)^v / (a^v Sqrt[s^2 + a^2]),
			    Abs[Im[a]], Infinity ] ] /;
	FreeQ[{a,v}, t] && Implies[NumberQ[N[v]], N[Re[v] > -1]],

mylaplace[ BesselJ[v_, a_. t_] CStep[t_] / t_, t_, s_,
	   st_, tlist_, slist_, options_ ] :>
	Block [	{},
		Assuming[ Positive[Re[v]], options ];
		Transform[ ( Sqrt[s^2 + a^2] - s )^v / ( v a^v ),
			    Abs[Im[a]], Infinity ] ] /;
	FreeQ[{a,v}, t] && Implies[NumberQ[N[v]], Re[N[v]] > 0],

mylaplace[ BesselK[0, j_. Sqrt[t_]] CStep[t_] / Sqrt[t_], t_, s_,
	   st_, tlist_, slist_, options_ ] :>
	Transform[ Sqrt[Pi] Exp[j^2 / (8 s)] BesselK[0, j^2 / (8 s)] /
		    (2 Sqrt[s]), 0, Infinity ] /;
	FreeQ[j, t],


(*	  F.  Exponential forms						*)

(*	      1.  exponential integral  [Churchill, 329]		*)
mylaplace[ ExpIntegralEi[a_. t_] CStep[t_], t_, s_,
	   st_, tlist_, slist_, options_ ] :>
	Block [	{},
		Assuming[ Negative[a], options ];
		Transform[ - Log[ 1 - s / a ] / s, 0, Infinity ] ] /;
	FreeQ[a, t] && Implies[NumberQ[N[a]], N[a < 0]],
						   (* [Churchill, 329]  *)

(*	      2.  error functions, erf					*)
mylaplace[ Erf[a_. Sqrt[t_]] CStep[t_], t_, s_,
	   st_, tlist_, slist_, options_ ] :>
	Transform[ a / ( s Sqrt[s + a^2] ), 0, Infinity ] /;
	FreeQ[a, t],			 (*  Modified [Churchill, 326]  *)

mylaplace[ Erf[a_. t_ + b_.] CStep[t_], t_, s_,
	   st_, tlist_, slist_, options_ ] :>
	Transform[ ( Exp[s^2 / (4 a^2) + s b / a] ( 1 - Erf[b + s / (2 a)] ) +
		      Erf[b] ) / s, 0, Infinity ] /;
	FreeQ[{a,b}, t],		    (*  [O & B, Formula 17.59]  *)

mylaplace[ Exp[a_/t_] CStep[t_], t_, s_, 
	   st_, tlist_, slist_, options_ ] :>
	Transform[ -2 I Sqrt[a] BesselK[-1, -2 I Sqrt[a] Sqrt[s]] / Sqrt[s],
		   0, Infinity ] /;
	FreeQ[a, t],		(* from Mathematica's Integrate command *)

mylaplace[ Exp[a_/t_] CStep[t_] / Sqrt[t_], t_, s_, 
	   st_, tlist_, slist_, options_ ] :>
	Transform[ Exp[2 I Sqrt[a] Sqrt[s]] Sqrt[Pi] / Sqrt[s], 0, Infinity ] /;
	FreeQ[a, t],		(* from Mathematica's Integrate command *)


(*	  G.  Trigonometric functions					*)

(*	      1.  sinc-like forms					*)
mylaplace[ Sin[a_. t_] CStep[t_] / t_, t_, s_,
		st_, tlist_, slist_, options_ ] :>
	Transform[ ArcTan[ a / s ], Abs[Im[a]], Infinity ] /;
	FreeQ[a, t],			      (*  [O & B, Formula 7.5]  *)

mylaplace[ Sin[k_. Sqrt[t_]] CStep[t_] / t_, t_, s_,
		st_, tlist_, slist_, options_ ] :>
	Transform[ Pi Erf[ k / ( 2 Sqrt[s] ) ], -Infinity, Infinity ] /;
	FreeQ[k, t],				  (*  [Churchill, 330]  *)

(*	      2.  sine integral Si					*)
mylaplace[ SinIntegral[a_. t_ + b_.] CStep[t_], t_, s_,
	   st_, tlist_, slist_, options_ ] :>
	Transform[ Exp[b s / a] ArcTan[a / s] / s, 0, Infinity ] /;
	FreeQ[{a,b}, t],			  (*  [Churchill, 330]  *)

(*	      3.  cosine integral Ci					*)
mylaplace[ CosIntegral[a_. t_] CStep[t_], t_, s_,
	   st_, tlist_, slist_, options_ ] :>
	Transform[ ( 2 Log[a] - Log[s^2 + a^2] ) / ( 2 s ), 0, Infinity ] /;
	Positive[a],				  (*  [Churchill, 330]  *)

mylaplace[ CosIntegral[a_. t_] CStep[t_], t_, s_,
	   st_, tlist_, slist_, options_ ] :>
	Transform[ - Log[1 + s^2/a^2] / (2 s), 0, Infinity ] /;
	FreeQ[a, t],				  (*  [Churchill, 330]  *)

(*	      4.  inverse trigonometric functions			*)
mylaplace[ ArcTan[a_. t_] CStep[t_], t_, s_, st_, tlist_, slist_, options_ ] :>
	Transform[ (CosIntegral[s/a] Sin[s/a] - SinIntegral[s/a] Cos[s/a]) / s,
		    0, Infinity ] /;
	FreeQ[a, t],			      (*  [O & B, Formula 8.4]  *)

mylaplace[ ArcCot[a_. t_] CStep[t_], t_, s_, st_, tlist_, slist_, options_ ] :>
	Transform[ ( Pi/2 - CosIntegral[s/a] Sin[s/a] -
		      SinIntegral[s/a] Cos[s/a] ) / s, 0, Infinity ] /;
	FreeQ[a, t],			      (*  [O & B, Formula 8.5]  *)


(*	  H.  Logarithmic forms						*)

mylaplace[ Log[a_. t_] CStep[t_], t_, s_, st_, tlist_, slist_, options_ ] :>
	Transform[ - a ( EulerGamma + Log[s / a] ) / s, 0, Infinity ] /;
	FreeQ[a, t],		     (*  Modified [O & B, Formula 6.1]  *)

mylaplace[ Log[a_. t_]^2 CStep[t_], t_, s_, st_, tlist_, slist_, options_ ] :>
	Transform[ a ( Pi^2 / 6 + ( EulerGamma + Log[s / a] )^2 ) / s,
		    0, Infinity ] /;
	FreeQ[a, t],			      (*  [O & B, Formula 6.2]  *)

mylaplace[ Log[a_ + b_. t_] CStep[t_], t_, s_,
	   st_, tlist_, slist_, options_ ] :>
	Block [	{},
		Assuming[ Negative[ Abs[Arg[b/a]] - Pi ], options ];
		Transform[ (Log[a] - Exp[a s / b] ExpIntegralEi[- a s / b]) / s,
			    0, Infinity ] ] /;
	FreeQ[{a,b},t] && Implies[NumberQ[N[a]] && NumberQ[N[b]], N[Abs[Arg[b/a]] < Pi]],				      (*  [O & B, Formula 6.7]  *)

mylaplace[ Log[t_^2 + b_] CStep[t_], t_, s_, st_, tlist_, slist_, options_ ] :>
	Block [	{a, trans},
		Assuming[ Positive[b], options];
		a = Sqrt[b];
		trans = 2 ( Log[a] - CosIntegral[a s] Cos[a s] -
			    SinIntegral[a s] Sin[a s] ) / s;
		Transform[trans, 0, Infinity] ] /;
	FreeQ[b, t] && Implies[ NumberQ[N[b]], Positive[b] ],
					     (*  [O & B, Formula 6.11]  *)

mylaplace[ Log[1 + b_. t_^2] CStep[t_] / t_, t_, s_,
	   st_, tlist_, slist_, options_ ] :>
	Block [	{a, trans},
		a = Sqrt[b];
		trans = CosIntegral[s/a]^2 + SinIntegral[s/a]^2;
		Transform[trans, 0, Infinity] ] /;
	FreeQ[b, t],			     (*  [O & B, Formula 6.15]  *)





(*  IV.   T R A N S F O R M     P R O P E R T I E S			*)


(*	  A.  pick off constants					*)
mylaplace[ c_ x_, t_, s_, st_, tlist_, slist_, options_ ] :>
	scaleL[mylaplace[x, t, s, st, tlist, slist, options], c] /;
	FreeQ[c, t] && ! FreeQ[x, t],


(*	  B.  additivity -- resulting ROC is intersection of two ROC's	*)
mylaplace[ (x_ + y_) CStep[t_], t_, s_, st_, tlist_, slist_, options_ ] :>
	addL[mylaplace[x CStep[t], t, s, st, tlist, slist, options],
	     mylaplace[y CStep[t], t, s, st, tlist, slist, options]],

mylaplace[ x_ + y_, t_, s_, st_, tlist_, slist_, options_ ] :>
	addL[mylaplace[x, t, s, st, tlist, slist, options],
	     mylaplace[y, t, s, st, tlist, slist, options]],

mylaplace[ (x_ + y_) CStep[t_] / c_, t_, s_, st_, tlist_, slist_, options_ ] :>
	addL[mylaplace[x CStep[t] / c, t, s, st, tlist, slist, options],
	     mylaplace[y CStep[t] / c, t, s, st, tlist, slist, options]],

mylaplace[ (x_ + y_) / c_, t_, s_, st_, tlist_, slist_, options_ ] :>
	addL[mylaplace[x / c, t, s, st, tlist, slist, options],
	     mylaplace[y / c, t, s, st, tlist, slist, options]],


(*	  C.  Time reversal						*)
mylaplace[ x_. CStep[-t_], t_, s_, st_, tlist_, slist_, options_ ] :>
	antiCausalL [ mylaplace [ (x /. t -> - t) CStep[t], t, s,
				  st, tlist, slist, options ],
		      s ],


(*	  D.  Shift and delays --  every continuous function should	*)
(*	      be a function times either a CStep  or an Delta, and	*)
(*	      the rule base already handles the Delta case.		*)
mylaplace[ f_. CStep[a_ t_ + b_.], t_, s_, st_, tlist_, slist_, options_ ] :>
	mylaplace[ f CStep[t + b/a] CStep[a] + f CStep[-t - b/a] CStep[-a],
		   t, s, st, tlist, slist, options ] /;
	FreeQ[{a, b}, t],			     (* [Bracewell, 67] *)

mylaplace[ f_. CStep[t_ + m_], t_, s_, st_, tlist_, slist_, options_ ] :>
	scaleL [ mylaplace [ (f /. t -> t - m) CStep[t], t, s,
			     st, tlist, slist, options ],
	         Exp[m s] ] /;
	FreeQ[m, t],

mylaplace[ f_. CStep[m_ - t_], t_, s_, st_, tlist_, slist_, options_ ] :>
	scaleL [ mylaplace [ (f /. t -> t + m) CStep[-t], t, s,
			     st, tlist, slist, options ],
	         Exp[- m s] ] /;
	FreeQ[m, t],

mylaplace[ f_[t_ + b_], t_, s_, st_, tlist_, slist_, options_ ] :>
	scaleL[ mylaplace[ f[t], t, s, st, tlist, slist, options],
		Exp[b s] ] /;
	FreeQ[b, t],

(*
mylaplace[ f_[t_ + b_] CStep[t_], t_, s_, st_, tlist_, slist_, options_ ] :>
	scaleL[ mylaplace[ f[t] CStep[t], t, s, st, tlist, slist, options],
		Exp[b s] ] /;
	FreeQ[b, t],
 *)


(*	  E.  Multiplication by c^(at+b) --  covers exponential case,	*)
(*            b can be a function of t					*)
mylaplace[ c_^(b_. + a_. t_) x_., t_, s_, st_, tlist_, slist_, options_ ] :>
	lMultiplyByExp [ mylaplace[c^b x, t, s, st, tlist, slist, options],
			 s, -a Log[c] ]  /;
	FreeQ[{a,c}, t],		   (* Modified [Franklin, 590]  *)


(*	  F.  Multiplication by t^m [Franklin, 590]			*)
mylaplace[ t_^m_. x_., t_, s_, st_, tlist_, slist_, options_ ] :>
	lDerivative[ mylaplace[x, t, s, st, tlist, slist, options], s, m ] /;
	IntegerQ[m] && m > 0,


(*	  G.  Modulation						*)

(*	      1.  multiplication by a cosine function [Bracewell, 224]	*)
mylaplace[ Cos[b_ + w_. t_] f_, t_, s_, st_, tlist_, slist_, options_ ] :>
	mylaplace [ Cos[b] Cos[w t] f - Sin[b] Sin[w t] f, t, s,
		    st, tlist, slist, options ],
mylaplace[ Cos[w_. t_] f_. CStep[t_], t_, s_, st_, tlist_, slist_, options_ ] :>
	Block [	{trans},
		trans = mylaplace[f CStep[t], t, s, st, tlist, slist, options];
		scaleL[addL[substituteForL[trans, s, s + I w],
			    substituteForL[trans, s, s - I w] ],
		       1/2] ] /;
	FreeQ[w, t],

(*	      2.  multiplication by a sine function [Bracewell, 224]	*)
mylaplace[ Sin[b_ + w_. t_] f_, t_, s_, st_, tlist_, slist_, options_ ] :>
	mylaplace [ Sin[b] Cos[w t] f + Cos[b] Sin[w t] f, t,
		    s, st, tlist, slist, options ],
mylaplace[ Sin[w_. t_] f_. CStep[t_], t_, s_, st_, tlist_, slist_, options_ ] :>
	Block [	{trans},
		trans = mylaplace[f CStep[t], t, s, st, tlist, slist, options];
		scaleL[subL[substituteForL[trans, s, s + I w],
			    substituteForL[trans, s, s - I w] ],
		       I/2] ] /;
	FreeQ[w, t],


(*	  H.  Derivative						*)
mylaplace[ Derivative[m_][f_][t_],
			t_, s_, st_, tlist_, slist_, options_ ] :>
	Block [ {dialogue},
		dialogue = SameQ[ Replace[Dialogue, options], All ];
		Assuming[ m > 0, dialogue ];
		If [ dialogue && ! IntegerQ[m],
		     Print[ "and that ", m, " is an integer" ] ];
		scaleL[ mylaplace[f[t], t, s, st, tlist, slist, options],
			s^m ] ] /;
	Implies[NumberQ[m], IntegerQ[m] && m > 0],    (* [Bracewell, 224] *)

mylaplace[ Derivative[m_][f_][t_] CStep[t_],
			t_, s_, st_, tlist_, slist_, options_ ] :>
	Block [ {dialogue},
		dialogue = SameQ[ Replace[Dialogue, options], All ];
		Assuming[ m > 0, dialogue ];
		If [ dialogue && ! IntegerQ[m],
		     Print[ "and that ", m, " is an integer" ] ];
		timeDerivative[mylaplace[f[t], t, s, st, tlist, slist, options],
			       s, m, f[t], t] ] /;
	Implies[NumberQ[m], IntegerQ[m] && m > 0],    (* [Bracewell, 224] *)


(*	  I.  Integral with time as upper limit				*)
mylaplace[ Integrate[f_, terms1___, {a_, 0, t_}, terms2___],
		       t_, s_, st_, tlist_, slist_, options_ ] :>
	Block [	{leftover, trans},
		leftover = ToCollection[ terms1, terms2 ];
		trans = mylaplace[f /. a -> t, t, s, st, tlist, slist, options];
		If [ SameQ[{leftover}, {}],
		     scaleL [ trans, 1/s ],
		     scaleL [ trans, 1/s Integrate[f, leftover] ] ] ],
						    (* [Churchill, 323] *)

mylaplace[ Integrate[f_, terms1___, t_, terms2___],
	   t_, s_, st_, tlist_, slist_, options_ ] :>
	Block [	{leftover, trans},
		leftover = ToCollection[ terms1, terms2 ];
		trans = mylaplace[f, t, s, st, tlist, slist, options];
		If [ SameQ[{leftover}, {}],
		     scaleL [ trans, 1/s ],
		     scaleL [ trans, 1/s Integrate[f, leftover] ] ] ],
						    (* [Churchill, 323] *)


(*	  J.  Divide by powers of t					*)
mylaplace[ f_. t_^m_, t_, s_, st_, tlist_, slist_, options_ ] :>
	integrateL[mylaplace[f t^(m+1), t, s, st, tlist, slist, options], s] /;
	IntegerQ[m] && m < 0,			    (*  [Nilsson, 516]  *)


(*	  K.  Conjugation:  L{ Conj f[-t] } --> Conj F(s)		*)
mylaplace[ Conjugate[x_], t_, s_, st_, tlist_, slist_, options_ ] :>
	conjL[mylaplace[x /. t -> -t, t, s, st, tlist, slist, options], s],
						  (*  [Bracewell, 122]  *)


(*	  L.  Convert forms with Abs[a t] into two-sided transforms	*)
mylaplace[ f_, t_, s_, st_, tlist_, slist_, options_ ] :>
	mylaplace[ absDialogue[f, t, options],
		   t, s, st, tlist, slist, options ] /;
	! FreeQ[ f, Abs[c_. t] ],




(*  V.    S T R U C T U R E S						*)


(*	  A.  Convolution						*)
mylaplace[ CConvolve[t_][x1_, x2_, rest__], t_, s_,
		st_, tlist_, slist_, op_ ] :>
	multL[mylaplace[x1, t, s, st, tlist, slist, op],
	      mylaplace[CConvolve[t][x2, rest], t, s,
			st, tlist, slist, op]],

mylaplace[ CConvolve[t_][x1_, x2_], t_, s_, st_, tlist_, slist_, op_ ] :>
	multL[mylaplace[x1, t, s, st, tlist, slist, op],
	      mylaplace[x2, t, s, st, tlist, slist, op]],

mylaplace[ CConvolve[tconv_][x1_, x2_], t_, s_, st_, tlist_, slist_, op_ ] :>
	convolveL[ CConvolve[Complement[tconv, {t}]],
		   mylaplace[x1, t, s, st, tlist, slist, op],
		   mylaplace[x2, t, s, st, tlist, slist, op]] /;
	ListQ[tconv] && MemberQ[tconv, t],


(*	  B.  Continuous FIR filters.					*)
mylaplace[ CFIR[t_, h_List, Roots -> r_], t_, s_,
	   st_, tlist_, slist_, options_ ] :>
	Block [ {i, numzeroes},
		If [ Length[h] != Length[r] + 1,
		     Message[ CFIR::invalid ] ];
		numzeroes = Length[r];
		Transform[ Product[(s - r[[i]]), {i, 1, numzeroes}],
			   -Infinity, Infinity ] ] /;
	Length[Dimensions[h]] == 1,

mylaplace[ CFIR[t_, h_, rest___], t_, s_, st_, tlist_, slist_, options_ ] :>
	Transform[ h . Table[s^k, {k, 0, Length[h] - 1}], -Infinity, Infinity ],

mylaplace[ CFIR[all__] [ x__ ], t_, s_, st_, tlist_, slist_, options_ ] :>
	multL[mylaplace[CFIR[all], t, s, st, tlist, slist, options],
	      mylaplace[x, t, s, st, tlist, slist, options]],


(*	  C.  One-dimensional analog IIR filters.			*)
(*	      Region of convergence is incorrect			*)
mylaplace[ CIIR[t_, a_List, Roots -> r_], t_, s_,
		st_, tlist_, slist_, options_ ] :>
	Block [ {i, numpoles},
		If [ Length[a] != Length[r] + 1,
		     Message[ CIIR::invalid ] ];
		numpoles = Length[r];
		rminus = Max[Re[r]];
		If [ ListQ[rminus], rminus = N[rminus] ];
		Transform[ 1 / Product[(s - r[[i]]), {i, 1, numpoles}],
			   rminus, Infinity ] ] /;
	Length[Dimensions[a]] == 1,

mylaplace[ CIIR[t_, a_List], t_, s_, st_, tlist_, slist_, options_ ] :>
	Block [	{alist, denom, index, rminus, len},
		alist = ToList[a];
		len = Length[alist];
		denom = a[[1]] +
			Sum[ alist[[index]] s^(index - 1), {index, 2, len} ];
		rminus = Max[ Re[ GetRootList[denom, s] ] ];
		Transform[ 1 / denom, rminus, Infinity ] ] /;
	Length[Dimensions[a]] == 1,

mylaplace[ CIIR[all__] [x__], t_, s_, st_, tlist_, slist_, options_ ] :>
	multL[mylaplace[CIIR[all], t, s, st, tlist, slist, options],
	      mylaplace[x, t, s, st, tlist, slist, options]],


(*	  D.  Imaginary part of a sequence				*)
mylaplace[ Im[x_], t_, s_, st_, tlist_, slist_, options_ ] :>
	Block [	{trans},
		trans = mylaplace[x, t, s, st, tlist, slist, options];
		scaleL[ subL [ trans,
			       conjL[substituteForL[trans, s, -s], s] ],
			1/2 ] ],


(*	  E.  Periodic sequence with period k				*)
mylaplace[ Periodic[a_, t_][f_] CStep[t_], t_, s_,
	   st_, tlist_, slist_, options_ ] :>
	scaleL[mylaplace[f CPulse[a, t], t, s, st, tlist, slist, options],
	       1 / ( 1 - Exp[- a s] ) ] /;
	FreeQ[a, t],


(*	  F.  Real part of a function					*)
mylaplace[ Re[x_], t_, s_, st_, tlist_, slist_, options_ ] :>
	Block [	{trans},
		trans = mylaplace[x, t, s, st, tlist, slist, options];
		scaleL [ addL [ trans,
				conjL[substituteForL[trans, s, -s], s] ],
			 1/2] ],


(*	  G.  Reverse operator						*)
mylaplace[ Rev[t_][x_], t_, s_, st_, tlist_, slist_, options_ ] :>
	antiCausalL[ mylaplace[ x, t, s, st, tlist, slist, options ], s ],


(*	  H.  Shift operator						*)
mylaplace[ Shift[m_, t_][x_], t_, s_, st_, tlist_, slist_, options_ ] :>
	scaleL[mylaplace[x, t, s, st, tlist, slist, options], Exp[- m s]] /;
	FreeQ[m, t],


(*	  I.  Summation operator					*)
mylaplace[ a_. Summation[i_, ib_, ie_, inc_][x_], t_, s_,
		st_, tlist_, slist_, options_ ] :>
	summationL[ mylaplace[a x, t, s, st, tlist, slist, options],
		    Summation[i, ib, ie, inc] ],



(*  VI.   S T R A T E G I E S						*)


(*	  A.  Similarity --  f(at) <--> F(s/a) / |a|  [Bracewell, 224]	*)
(*	 	only perform this if a is neither 1 nor 0		*)
(*		must be done after operator rules because the		*)
(*		substitution t -> t/scale messes up operators		*)
mylaplace[ f_ CStep[t_], t_, s_, st_, tlist_, slist_, options_ ] :>
	Block [	{newf, scale},
		scale = ScalingFactor[f, t];
		newf = ( f /. t -> t/scale ) CStep[t];
		similarityL[ mylaplace[newf, t, s, st, tlist, slist, options],
			     s,
			     scale ] ] /;
	similarityQ[f, t],

mylaplace[ f_, t_, s_, st_, tlist_, slist_, options_ ] :>
	Block [	{newf, scale},
		scale = ScalingFactor[f, t];
		newf = ( f /. t -> t/scale );
		similarityL[ mylaplace[newf, t, s, st, tlist, slist, options],
			     s,
			     scale ] ] /;
	similarityQ[f, t],


(*	  B.  Place sub-expressions over a common denominator		*)
mylaplace[ f_. a_^(v_. t_ + k_.) / b_^(u_. t_ + l_.), t_, s_,
	   st_, tlist_, slist_, options_ ] :>
	mylaplace[ (a^v/b^u)^t f a^k/b^l, t, s, st, tlist, slist, options ],


(*	  C.  Expand out products like (t + 1) (t + 2) ...		*)
mylaplace[ x_, t_, s_, st_, tlist_, slist_, options_ ] :>
	mylaplace[ Distribute[x], t, s, st, tlist, slist, options ]  /;
	SameQ[Head[x], Times] && ! SameQ[Distribute[x], x],


(*	  D.  Expands out all numerator in the expression		*)
mylaplace[ x_, t_, s_, st_, tlist_, slist_, options_ ] :>
	mylaplace [ Expand[x], t, s,
		    SetStateField[st, expandfield, False],
		    tlist, slist, options ]  /;
	GetStateField[st, expandfield] && ! SameQ[x, Expand[x]],


(*	  E.  Expands out all numerators and denominators in expression	*)
mylaplace[ x_, t_, s_, st_, tlist_, slist_, options_ ] :>
	mylaplace[ ExpandAll[x], t, s,
		   SetStateField[st, expandallfield, False],
		   tlist, slist, options ] /;
	GetStateField[st, expandallfield] && ! SameQ[x, ExpandAll[x]],


(*	  F.  Collect all terms in expression				*)
mylaplace[ x_, t_, s_, st_, tlist_, slist_, options_ ] :>
	mylaplace[ MyCollectAll[x, t], t, s,
		   SetStateField[st, collectallfield, False],
		   tlist, slist, options ] /;
	GetStateField[st, collectallfield],


(*	  G.  Reduces all signal processing operations to their		*)
(*		mathematical forms					*)
mylaplace[ x_, t_, s_, st_, tlist_, slist_, options_ ] :>
	Block [	{newx},
		newx = ToContinuous[ TheFunction[x] ];
		state = If [ SameQ[newx, x], st, initLstate[] ];
		state = SetStateField[state, thefunfield, False];

		mylaplace[ newx, t, s, state, tlist, slist, options ] ] /;
	GetStateField[st, thefunfield],


(*	  H.  Apply definition if flag is set				*)
mylaplace[ x_, t_, s_, st_, tlist_, slist_, options_ ] :>
	Block [	{state, trans},
		state = SetStateField[st, definitionfield, False];
		trans = Integrate[x Exp[- s t], {t, -Infinity, Infinity}];
		If [ SameQ[Head[trans], Integrate],
		     mylaplace[x, t, s, state, tlist, slist, options],
		     definitionDialogue[ x CStep[t],
					 Transform[ trans, 0, Infinity ],
					 Integrate, options ] ] ] /;
	GetStateField[st, definitionfield] && Replace[Definition, options],


(*	  I.  Two-sided transform if all else fails			*)
mylaplace[ x_, t_, s_, st_, tlist_, slist_, options_ ] :>
	Block [	{trans},
		trans = MyLaPlace[ x CStep[t] + x CStep[-t], t, s,
				   nullLstate[], tlist, slist, options ];
		If [ TrueQ[LForm[trans] && TheFunction[trans] != 0],
		     MyMessage[Transform::twosided, trans, x],
		     mylaplace[x, t, s, state, tlist, slist, options] ] ] /;
	GetStateField[st, stepfield]

}


(*  E N D     P A C K A G E   *)

End[]
EndPackage[]

If [ TrueQ[ $VersionNumber >= 2.0 ],
     On[ General::spell ];
     On[ General::spell1 ] ];


(*  A L I A S E S  *)

Unprotect[ LaPlaceTransform ]
LaPlaceTransform = LaPlace
LaPlaceTransform::usage = LaPlace::usage
Protect[ LaPlaceTransform ]


(*  H E L P     I N F O R M A T I O N  *)

Combine[ SPfunctions, { LaPlace } ]
Protect[ LaPlace ]


(*  E N D     M E S S A G E  *)

Print["The forward Laplace transform rule base LaPlace has been loaded."]
Null
