(*:Mathematica Version: 4.0 *)

(*:Package Version: 1.14 *)

(* :Copyright: Copyright 1990-1999, Wolfram Research, Inc.*)

(*:Name: Calculus`FourierTransform` *)

(*:Context: Calculus`FourierTransform` *)

(*:Title: Fourier Transform *)

(*:Author: Wolfram Research, Inc. *)

(*:Summary:
This package implements numerical approximations to Fourier transforms
(exponential and trigonometric), Fourier coefficients and series (exponential
and trigonometric) and related numerical approximations, and discrete-time
Fourier transforms and related numerical approximations.
*)

(*:Keywords: Fourier, transform *)

(*:Requirements: None. *)

(*:Source:
	R. A. Roberts, C. T. Mullis, Digital Signal Processing,
	Addison-Wesley Publishing Company, 1987, Figure 4.1.1,
	"Four classes of Fourier transforms."
*)

(*:History:
	Version 1.1 by Eran Yehudai, October 1990.
	Versions 1.2-1.13 by ECM and Jeff Adams (Wolfram Research),
		January 1991-June 1997.
	Version 1.14, ECM, Jan. 1998.  Removed rules for FourierTransform,
	  InverseFourierTransform, FourierCosTransform,
	  InverseFourierCosTransform, FourierSinTransform, and
	  InverseFourierSinTransform.  Revised rules for NFourierTransform
	  and NInverseFourierTransform.  Added rules for NFourierCosTransform,
	  NInverseFourierCosTransform, NFourierSinTransform, and
	  NInverseFourierSinTransform.  Added rules for DTFourierTransform,
	  InverseDTFourierTransform, NDTFourierTransform, and
	  NInverseDTFourierTransform (discrete-time Fourier transforms).
	  Replaced FourierExpSeries with FourierSeries,
	  FourierExpSeriesCoefficient with FourierCoefficient,
	  NFourierExpSeries with NFourierSeries, and
	  NFourierExpSeriesCoefficient with NFourierCoefficient.  Added
	  rules for InverseFourierCoefficient and NInverseFourierCoefficient.
	  Revised FourierTrigSeries and NFourierTrigSeries.
	  Replaced FourierSinSeriesCoefficient with FourierSinCoefficient,
	  NFourierSinSeriesCoefficient with NFourierSinCoefficient,
	  FourierCosSeriesCoefficient with FourierCosCoefficient, and
	  NFourierCosSeriesCoefficient with NFourierCosCoefficient. 
		
*)

(* :Limitations: *)

(*:Discussion:

continuous-time, continuous-frequency:
	FourierTransform & InverseFourierTransform (kernel)
	(These functions map a function in continuous-time to a
		 function in continuous-frequency and visa versa.)
	NFourierTransform & NInverseFourierTransform (package)
	(These functions are numerical approximations.) 

discrete-time, discrete-frequency:
	Fourier & InverseFourier (kernel)
	(These functions map a list to a list, not a function to a function.)

discrete-time, continuous-frequency:
	DTFourierTransform & InverseDTFourierTransform (package)
	(These functions map a function in discrete-time to a
		 function in continuous-frequency and visa versa.)
	NDTFourierTransform & NInverseDTFourierTransform (package)
	(These functions are numerical approximations.)

discrete-frequency, continuous-time:
	FourierCoefficient & InverseFourierCoefficient (package)
	(These functions map a function in continuous-time to a
		 function in discrete-frequency and visa versa.)
	NFourierCoefficient & NInverseFourierCoefficient (package)
	(These functions are numerical approximations.)
	FourierSinCoefficient & FourierCosCoefficient (package)
	(These functions map a function in continuous-time to a
		function in discrete-frequency.)
	NFourierSinCoefficient & NFourierCosCoefficient (package)
	(These functions are numerical approximations.)
        FourierSeries and FourierTrigSeries (package) each take a function and
		give an approximation to that function based on a truncated
		series expansion.  NFourierSeries and NFourierTrigSeries do the
		same thing, but use numerical approximations to the
		coefficients.

*)

BeginPackage["Calculus`FourierTransform`", "Utilities`FilterOptions`"]
	
$FourierFrequencyConstant::usage = 
"$FourierFrequencyConstant is an obsolete default setting for the obsolete
option FourierFrequencyConstant.  The FourierFrequencyConstant option has been
superceded by the constant b in the new option setting
FourierParameters -> {a, b}."

FourierFrequencyConstant::usage =
"FourierFrequencyConstant is an obsolete option to FourierTransform and related
functions, superceded by the constant b in the new option setting
FourierParameters -> {a, b}."

$FourierOverallConstant::usage = 
"$FourierOverallConstant is is an obsolete default setting for the obsolete
option FourierOverallConstant.  Given the new option setting
FourierParameters -> {a, b}, the FourierOverallConstant option setting now
corresponds to the expression Sqrt[Abs[b] (2 Pi)^(a-1)]."

FourierOverallConstant::usage =
"FourierOverallConstant is is an obsolete option to FourierTransform and related
functions.  Given the new option setting FourierParameters -> {a, b},
the FourierOverallConstant option setting now corresponds to the
expression Sqrt[Abs[b] (2 Pi)^(a-1)]."

FourierSample::usage =
"FourierSample[f, {t, t0, t1, dt}, w0] is an obsolete function."

FourierExpSeries::usage = 
"FourierExpSeries[expr, {t, -t1, t1}, k] is an obsolete function,
superceded by FourierSeries[expr, t, k, FourierParameters -> {-1, -1/(2 t1)}]."

FourierExpSeriesCoefficient::usage = 
"FourierExpSeriesCoefficient[expr, {t, -t1, t1}, n] is an obsolete function,
superceded by
FourierCoefficient[expr, t, n, FourierParameters -> {-1, -1/(2 t1)}]."

NFourierExpSeries::usage =
"NFourierExpSeries[expr, {t, -t1, t1}, k] is an obsolete function,
superceded by NFourierSeries[expr, t, k, FourierParameters -> {-1, -1/(2 t1)}]."

NFourierExpSeriesCoefficient::usage = 
"NFourierExpSeriesCoefficient[expr, {t, -t1, t1}, n] is an obsolete function,
superceded by
NFourierCoefficient[expr, t, n, FourierParameters -> {-1, -1/(2 t1)}]."

FourierSinSeriesCoefficient::usage =
"FourierSinSeriesCoefficient[expr, {t, -t1, t1}, n] is an obsolete function,
superceded by FourierSinCoefficient[expr, t, n, 
FourierParameters -> {-1, 1/(2 t1)}], n > 0."

FourierCosSeriesCoefficient::usage =
"FourierCosSeriesCoefficient[expr, {t, -t1, t1}, n] is an obsolete function,
superceded by FourierCosCoefficient[expr, t, n,
FourierParameters -> {-1, 1/(2 t1)}], n >= 0."

NFourierSinSeriesCoefficient::usage =
"NFourierSinSeriesCoefficient[expr, {t, -t1, t1}, n] is an obsolete function,
superceded by NFourierSinCoefficient[expr, t, n,
FourierParameters -> {-1, 1/(2 t1)}], n > 0."

NFourierCosSeriesCoefficient::usage =
"NFourierCosSeriesCoefficient[expr, {t, -t1, t1}, n] is an obsolete function,
superceded by NFourierCosCoefficient[expr, t, n,
FourierParameters -> {-1, 1/(2 t1)}], n >= 0."



(* ===================== numeric Fourier Transform ======================= *)

NFourierTransform::usage = 
"NFourierTransform[expr, t, w] gives the numerical value of the Fourier 
transform of expr, a function of t, at w.  It is defined by
1/Sqrt[2 Pi] NIntegrate[expr Exp[I w t], {t, -Infinity, Infinity}].  
NFourierTransform[expr, t, w, FourierParameters -> {a, b}] gives the
numerical value of the parameterized transform
Sqrt[Abs[b]/(2 Pi)^(1-a)] NIntegrate[expr Exp[I b w t],
{t, -Infinity, Infinity}]."

NInverseFourierTransform::usage = 
"NInverseFourierTransform[expr, w, t] gives the numerical value of the inverse
Fourier transform of expr, a function of w, at t.  It is defined by
1/Sqrt[2 Pi] NIntegrate[expr Exp[-I w t], {w, -Infinity, Infinity}].
NInverseFourierTransform[expr, w, t, FourierParameters -> {a, b}] gives
the numerical value of the parameterized inverse transform
Sqrt[Abs[b]/(2 Pi)^(1+a)] NIntegrate[expr Exp[-I b w t],
{w, -Infinity, Infinity}]."

Options[NFourierTransform] = Options[NInverseFourierTransform] =
	Sort[Join[{FourierParameters -> {0, 1}}, Options[NIntegrate]]]
	
(* ==================== numeric Fourier Sin Transform ==================== *)

NFourierSinTransform::usage =
"NFourierSinTransform[expr, t, w] gives the numerical value of the Fourier sine
transform of expr, a function of t, at w.  It is defined by
Sqrt[2/Pi] NIntegrate[expr Sin[w t], {t, 0, Infinity}].  
NFourierSinTransform[expr, t, w, FourierParameters -> {a, b}] gives
the numerical value of the parameterized transform
2 Sqrt[Abs[b]/(2 Pi)^(1-a)] NIntegrate[expr Sin[b w t], {t, 0, Infinity}]."

NInverseFourierSinTransform::usage =
"NInverseFourierSinTransform[expr, w, t] gives the numerical value of the 
inverse Fourier sine transform of expr, a function of w, at t.  It is defined by
Sqrt[2/Pi] NIntegrate[expr Sin[w t], {w, 0, Infinity}].
NInverseFourierSinTransform[expr, w, t, FourierParameters -> {a, b}] gives
the numerical value of the parameterized inverse transform
2 Sqrt[Abs[b]/(2 Pi)^(1+a)] NIntegrate[expr Sin[b w t], {w, 0, Infinity}]."

Options[NFourierSinTransform] = Options[NInverseFourierSinTransform] =
        Sort[Join[{FourierParameters -> {0, 1}}, Options[NIntegrate]]]
	

(* ==================== numeric Fourier Cos Transform ==================== *)

NFourierCosTransform::usage =
"NFourierCosTransform[expr, t, w] gives the numerical value of the Fourier 
cosine transform of expr, a function of t, at w.  It is defined by
Sqrt[2/Pi] NIntegrate[expr Cos[w t], {t, 0, Infinity}].  
NFourierCosTransform[expr, t, w, FourierParameters -> {a, b}] gives
the numerical value of the parameterized transform
2 Sqrt[Abs[b]/(2 Pi)^(1-a)] NIntegrate[expr Cos[b w t], {t, 0, Infinity}]."

NInverseFourierCosTransform::usage =
"NInverseFourierCosTransform[expr, w, t] gives the numerical value of the 
inverse Fourier cosine transform of expr, a function of w, at t.  It is defined
by Sqrt[2/Pi] NIntegrate[expr Cos[w t], {w, 0, Infinity}].
NInverseFourierCosTransform[expr, w, t, FourierParameters -> {a, b}] gives
the numerical value of the parameterized inverse transform
2 Sqrt[Abs[b]/(2 Pi)^(1+a)] NIntegrate[expr Cos[b w t], {w, 0, Infinity}]."

Options[NFourierCosTransform] = Options[NInverseFourierCosTransform] =
        Sort[Join[{FourierParameters -> {0, 1}}, Options[NIntegrate]]]
	

(* =================== discrete-time Fourier Transform ===================== *)

(* w may be symbolic or real-valued *)
(*
  DTFourierTransform[expr, n, w] gives the discrete time Fourier transform
  of expr, a function of n, at w.  It is defined by
  Sum[expr Exp[2 Pi I n w], {n, -Infinity, Infinity}], where the sum is
  periodic in w, with a period of 1.
  DTFourierTransform[expr, n, w, FourierParameters -> {a, b}] gives the
  parameterized transform Abs[b]^((1-a)/2) Sum[expr Exp[2 Pi I b n w],
  {n, -Infinity, Infinity}], where the period of the sum is 1/Abs[b]. *)
DTFourierTransform::usage = 
"DTFourierTransform[expr, n, w] gives the discrete time Fourier transform
of expr, a function of n, at w.  This transform is periodic in w, with a period
of 1.  DTFourierTransform[expr, n, w, FourierParameters -> {a, b}] gives the
discrete time Fourier transform of expr, where the transform has a period of
1/Abs[b]."

(* NOTE: DTFourierTransform makes use of Sum which currently does not
	support options.  So there is no need for DTFourierTransform to
	support additional Sum options.  *)
Options[DTFourierTransform] = {FourierParameters -> {0, 1}}

(* n may be symbolic or integer-valued *)
(*
  InverseDTFourierTransform[expr, w, n] gives the inverse discrete time
  Fourier transform of expr, a periodic function of w, at n.  It is defined by
  Integrate[expr Exp[-2 Pi I n w], {w, -1/2, 1/2}], where the period of expr 
  is 1.  InverseDTFourierTransform[expr, w, n, FourierParameters -> {a, b}] 
  gives the parameterized inverse transform 
  Abs[b]^((1+a)/2) Integrate[expr Exp[-2 Pi I b n w],
  {w, -1/(2 Abs[b]), 1/(2 Abs[b])}], where the period of expr is 1/Abs[b].
*)
InverseDTFourierTransform::usage = 
"InverseDTFourierTransform[expr, w, n] gives the inverse discrete time Fourier
transform of a periodic function of w, at n.  The function is equal to expr for
-1/2 <= w <= 1/2, and has a period of 1.
InverseDTFourierTransform[expr, w, n, FourierParameters -> {a, b}] gives
the inverse discrete time Fourier transform of a periodic function, where the
function is equal to expr for -1/(2 Abs[b]) <= w <= 1/(2 Abs[b]), and has a
period of 1/Abs[b]."

Options[InverseDTFourierTransform] =
        Sort[Join[{FourierParameters -> {0, 1}}, Options[Integrate]]]
	

(* =============== numeric discrete-time Fourier Transform =============== *)

(* w must be real-valued *)
(*
  NDTFourierTransform[expr, n, w] gives the numerical value of the discrete time
  Fourier transform of expr, a function of n, at w.  It is defined by
  NSum[expr Exp[2 Pi I n w], {n, -Infinity, Infinity}], where the sum 
  is periodic in w, with a period of 1.
  NDTFourierTransform[expr, n, w, FourierParameters -> {a, b}] gives 
  the numerical value of the parameterized transform
  Abs[b]^((1-a)/2) NSum[expr Exp[2 Pi I b n w], {n, -Infinity, Infinity}],
  where the period of the sum is 1/Abs[b]. *)
NDTFourierTransform::usage = 
"NDTFourierTransform[expr, n, w] gives the numerical value of the discrete time
Fourier transform of expr, a function of integer n, at real values of w.  This 
transform is periodic in w, with a period of 1.  
NDTFourierTransform[expr, n, w, FourierParameters -> {a, b}] gives 
the numerical value of the discrete-time Fourier transform of expr at real 
values of w, where the transform has a period of 1/Abs[b]."

Options[NDTFourierTransform] =
	Sort[Join[{FourierParameters -> {0, 1}}, Options[NSum]]]

(* n must be integer-valued *)
(*
  NInverseDTFourierTransform[expr, w, n] gives the numerical value of the 
  inverse discrete time Fourier transform of expr, a periodic function of w, at
  integer n.  It is defined by NIntegrate[expr Exp[-2 Pi I n w],
  {w, -1/2, 1/2}], where the period of expr is 1.
  NInverseDTFourierTransform[expr, w, n, FourierParameters -> {a, b}] gives
  the numerical value of the parameterized inverse transform
  Abs[b]^((1+a)/2) NIntegrate[expr Exp[-2 Pi I b n w],
  {w, -1/(2 Abs[b]), 1/(2 Abs[b])}], where the period of expr is 1/Abs[b]. *)
NInverseDTFourierTransform::usage = 
"NInverseDTFourierTransform[expr, w, n] gives the numerical value of the
inverse discrete time Fourier transform of a periodic function of w, at
integer values of n.  The function is equal to expr for -1/2 <= w <= 1/2,
and has a period of 1.  
NInverseDTFourierTransform[expr, w, n, FourierParameters -> {a, b}] gives the
numerical value of the inverse discrete time Fourier transform of a periodic
function, where the function is equal to expr for
-1/(2 Abs[b]) <= w <= 1/(2 Abs[b]), and has a period of 1/Abs[b]."

Options[NInverseDTFourierTransform] =
        Sort[Join[{FourierParameters -> {0, 1}}, Options[NIntegrate]]]
	

(* ========== Fourier Series (discrete-frequency Fourier Transform) ======== *)

(* n may be symbolic or integer-valued *)
(* These coefficients are typically referred to as the Fourier spectrum. *)
(*
  FourierCoefficient[expr, t, n] gives the nth coefficient in the
  Fourier exponential series expansion of the periodic function of t that is
  equal to expr for -1/2 <= t <= 1/2, repeating with period 1,
  defined by Integrate[expr Exp[2 Pi I n t], {t, -1/2, 1/2}].
  FourierCoefficient[expr, t, n, FourierParameters -> {a, b}] gives 
  Abs[b]^((1-a)/2) Integrate[expr Exp[2 Pi I b n t],
  {t, -1/(2 Abs[b]), 1/(2 Abs[b])}], the nth coefficient in the
  Fourier exponential series expansion of the periodic function of
  t that is equal to expr for -1/(2 Abs[b]) <= t <= 1/(2 Abs[b]), repeating with
  period 1/Abs[b]. *)
FourierCoefficient::usage = 
"FourierCoefficient[expr, t, n] gives the nth coefficient in the
Fourier exponential series expansion of the periodic function of t that is
equal to expr for -1/2 <= t <= 1/2, and has a period of 1.
FourierCoefficient[expr, t, n, FourierParameters -> {a, b}] gives 
the nth coefficient in the Fourier exponential series expansion of the periodic
function of t that is equal to expr for -1/(2 Abs[b]) <= t <= 1/(2 Abs[b]),
and has a period of 1/Abs[b]."

Options[FourierCoefficient] =
	Sort[Join[{FourierParameters -> {0, 1}}, Options[Integrate]]]

(* t may be symbolic or real-valued *)
(*
  InverseFourierCoefficient[expr, n, t] gives the Fourier exponential series
  representation of a periodic function of t, whose coefficients are
  given by expr, a function of n.  It is defined by
  Sum[expr Exp[-2 Pi I n t], {n, -Infinity, Infinity}], where the sum has a 
  period of 1.
  InverseFourierCoefficient[expr, n, t, FourierParameters -> {a, b}] gives
  the inverse coefficient
  Abs[b]^((1+a)/2) Sum[expr Exp[-2 Pi I b n t], {n, -Infinity, Infinity}], where
  the period of the sum is 1/Abs[b]. *)
InverseFourierCoefficient::usage = 
"InverseFourierCoefficient[expr, n, t] gives the Fourier exponential series
representation of a periodic function of t, where the function has a period
of 1, and the series coefficients are given by expr, indexed by n.
InverseFourierCoefficient[expr, n, t, FourierParameters -> {a, b}] gives the
Fourier exponential series representation of a periodic function of t, where
the function has a period of 1/Abs[b]."

(* NOTE: InverseFourierCoefficient makes use of Sum which currently does not
	support options.  So there is no need for InverseFourierCoefficient to
	support additional Sum options.  *)
Options[InverseFourierCoefficient] = {FourierParameters -> {0, 1}}

(* k must be nonnegative integer-valued *)
(*
  FourierSeries[expr, t, k] finds the Fourier coefficients c[n], -k <= n <= k,
  for the periodic function of t that is equal to expr for -1/2 <= t <= 1/2,
  repeating with period 1, and gives
  Sum[c[n] Exp[-2 Pi I n t], {n, -k, k}], the kth order Fourier exponential 
  series approximation to the function.
  FourierSeries[expr, t, k, FourierParameters -> {a, b}] gives
  Abs[b]^((1+a)/2) Sum[c[n] Exp[-2 Pi I b n t], {n, -k, k}], the kth order
  Fourier exponential series approximation to the periodic function of t that is
  equal to expr for -1/(2 Abs[b]) <= t <= 1/(2 Abs[b]), repeating with period
  1/Abs[b]. *)
FourierSeries::usage =
"FourierSeries[expr, t, k] gives the kth order Fourier exponential series
approximation to the periodic function of t that is equal to expr for
-1/2 <= t <= 1/2, and has a period of 1.
FourierSeries[expr, t, k, FourierParameters -> {a, b}] gives the kth order
Fourier exponential series approximation to the periodic function of t that is
equal to expr for -1/(2 Abs[b]) <= t <= 1/(2 Abs[b]), and has a period of
1/Abs[b]."

Options[FourierSeries] = Options[FourierCoefficient]


(* ==== numeric  Fourier Series (discrete-frequency Fourier Transform) === *)

(* n must be integer-valued *)
(*
  NFourierCoefficient[expr, t, n] gives the numerical value of the nth 
  coefficient in the Fourier exponential series expansion of the periodic 
  function of t that is equal to expr for -1/2 <= t <= 1/2, repeating with 
  period 1, defined by NIntegrate[expr Exp[2 Pi I n t], {t, -1/2, 1/2}].
  NFourierCoefficient[expr, t, n, FourierParameters -> {a, b}] gives
  Abs[b]^((1-a)/2) NIntegrate[expr Exp[2 Pi I b n t],
  {t, -1/(2 Abs[b]), 1/(2 Abs[b])}], the numerical value of the nth coefficient
  in the Fourier exponential series expansion of the periodic function of t
  that is equal to expr for -1/(2 Abs[b]) <= t <= 1/(2 Abs[b]), repeating with
  period 1/Abs[b]. *)
NFourierCoefficient::usage = 
"NFourierCoefficient[expr, t, n] gives the numerical value of the nth 
coefficient in the Fourier exponential series expansion of the periodic function
of t that is equal to expr for -1/2 <= t <= 1/2, and has a period of 1.
NFourierCoefficient[expr, t, n, FourierParameters -> {a, b}] gives
the numerical value of the nth coefficient in the Fourier exponential series 
of the periodic function of t that is equal to expr for
-1/(2 Abs[b]) <= t <= 1/(2 Abs[b]), and has a period of 1/Abs[b]."

Options[NFourierCoefficient] =
	Sort[Join[{FourierParameters -> {0, 1}}, Options[NIntegrate]]]

(* t must be real-valued *)
(*
  NInverseFourierCoefficient[expr, n, t] gives the numerical value of the
  Fourier exponential series representation of a periodic function of t, whose
  coefficients are given by expr, a function of n.  It is defined by 
  NSum[expr Exp[-2 Pi I n t], {n, -Infinity, Infinity}], where the sum
  has a period of 1.
  NInverseFourierCoefficient[expr, n, t, FourierParameters -> {a, b}]
  gives the numerical value of the inverse coefficient
  Abs[b]^((1+a)/2) NSum[expr Exp[-2 Pi I b n t], {n, -Infinity, Infinity}], 
  where the period of the sum is 1/Abs[b]. *)
NInverseFourierCoefficient::usage =
"NInverseFourierCoefficient[expr, n, t] gives the numerical value of the
Fourier exponential series representation of a periodic function of t, where the
function has a period of 1, and the series coefficients are given by expr,
indexed by n.
NInverseFourierCoefficient[expr, n, t, FourierParameters -> {a, b}] gives
the numerical value of the Fourier exponential series representation of a
periodic function of t, where the function has a period of 1/Abs[b]."

Options[NInverseFourierCoefficient] =
	Sort[Join[{FourierParameters -> {0, 1}}, Options[NSum]]]

(* k must be nonnegative integer-valued *)
(* Note that the numeric aspect of NFourierSeries is that NFourierCoefficient
        is used, instead of FourierCoefficient.  NFourierSeries uses Sum just
        as FourierSeries does;  it does *not* use NSum.  So "NFourierSeries"
        may be a misuse of the N* naming convention.  But the alternative, 
        subsuming NFourierSeries into FourierSeries (i.e., by picking
        FourierCoefficient or NFourierCoefficient based on an option), wouldn't
        work well either.  Note that FourierCoefficient supports Integrate
        options while NFourierCoefficient supports NIntegrate options. *)
(*
  NFourierSeries[expr, t, k] finds the numerical values of the Fourier 
  coefficients c[n], -k <= n <= k, for the periodic function of t that is equal 
  to expr for -1/2 <= t <= 1/2, repeating with period 1, and gives
  Sum[c[n] Exp[-2 Pi I n t], {n, -k, k}], the kth order Fourier exponential 
  series approximation to the function.
  NFourierSeries[expr, t, k, FourierParameters -> {a, b}] gives
  Abs[b]^((1+a)/2) Sum[c[n] Exp[-2 Pi I b n t], {n, -k, k}], the 
  kth order Fourier exponential series approximation to the periodic function of
  t that is equal to expr for -1/(2 Abs[b]) <= t <= 1/(2 Abs[b]), repeating with
  period 1/Abs[b], where the c[n] are numerical coefficients. *)
NFourierSeries::usage =
"NFourierSeries[expr, t, k] uses numerical coefficients to give the kth order
Fourier exponential series approximation to the periodic function of t that is
equal to expr for -1/2 <= t <= 1/2, and has a period of 1.
NFourierSeries[expr, t, k, FourierParameters -> {a, b}] uses numerical
coefficients to give the kth order Fourier exponential series approximation to
the periodic function of t that is equal to expr for
-1/(2 Abs[b]) <= t <= 1/(2 Abs[b]), and has a period of 1/Abs[b]."

Options[NFourierSeries] = Options[NFourierCoefficient]
	

(*  ===================== Fourier Trigonometric Series ===================== *)

(* Note: old syntax...
  FourierSinSeriesCoefficient[expr, {x, x0, x1}, n] gives the coefficient of
  Sin[2Pi n x / (x1-x0)] in the Fourier trigonometric series expansion of expr
  (n > 0).
*)
(*
  FourierSinCoefficient[expr, t, n] gives the coefficient of Sin[2 Pi n t], 
  n > 0, in the Fourier trigonometric series expansion of the periodic function
  of t that is equal to expr for -1/2 <= t <= 1/2, repeating with period 1,
  defined by 2 Integrate[expr Sin[2 Pi n t], {t, -1/2, 1/2}].
  FourierSinCoefficient[expr, t, n, FourierParameters -> {a, b}] gives
  2 Abs[b]^((1-a)/2) Integrate[expr Sin[2 Pi b n t],
  {t, -1/(2 Abs[b]), 1/(2 Abs[b])}], the coefficient of Sin[2 Pi b n t] in
  the Fourier trigonometric series expansion of the periodic function of t that
  is equal to expr for -1/(2 Abs[b]) <= t <= 1/(2 Abs[b]), repeating with
  period 1/Abs[b]. *)
(* n may be symbolic or integer-valued *)
FourierSinCoefficient::usage =
"FourierSinCoefficient[expr, t, n] gives the coefficient of Sin[2 Pi n t], 
n > 0, in the Fourier trigonometric series expansion of the periodic function
of t that is equal to expr for -1/2 <= t <= 1/2, and has a period of 1.
FourierSinCoefficient[expr, t, n, FourierParameters -> {a, b}] gives
the coefficient of Sin[2 Pi b n t] in the Fourier trigonometric series expansion
of the periodic function of t that is equal to expr for
-1/(2 Abs[b]) <= t <= 1/(2 Abs[b]), and has a period of 1/Abs[b]."

(* Note: old syntax...
  FourierCosSeriesCoefficient[expr, {x, x0, x1}, n] gives the coefficient of
  Cos[2Pi n x / (x1-x0)] in the Fourier trigonometric series expansion of expr
  (n >= 0).
*)
(*
  FourierCosCoefficient[expr, t, n] gives the coefficient of Cos[2 Pi n t],
  n >= 0, in the Fourier trigonometric series expansion of the periodic function
  of t that is equal to expr for -1/2 <= t <= 1/2, repeating with period 1,
  defined by If[n===0, 1, 2] Integrate[expr Cos[2 Pi n t], {t, -1/2, 1/2}].
  FourierCosCoefficient[expr, t, n, FourierParameters -> {a, b}]
  gives If[n===0, 1, 2] Abs[b]^((1-a)/2) Integrate[expr Cos[2 Pi b n t],
  {t, -1/(2 Abs[b]), 1/(2 Abs[b])}], the coefficient of Cos[2 Pi b n t] in
  the Fourier trigonometric series expansion of the periodic function of t that
  is equal to expr for -1/(2 Abs[b]) <= t <= 1/(2 Abs[b]), repeating with
  period 1/Abs[b]. *)
(* n may be symbolic or integer-valued *)
FourierCosCoefficient::usage =
"FourierCosCoefficient[expr, t, n] gives the coefficient of Cos[2 Pi n t],
n >= 0, in the Fourier trigonometric series expansion of the periodic function
of t that is equal to expr for -1/2 <= t <= 1/2, and has a period of 1.
FourierCosCoefficient[expr, t, n, FourierParameters -> {a, b}] gives
the coefficient of Cos[2 Pi b n t] in the Fourier trigonometric series expansion
of the periodic function of t that is equal to expr for
-1/(2 Abs[b]) <= t <= 1/(2 Abs[b]), and has a period of 1/Abs[b]."

(* NOTE: old syntax...
	FourierTrigSeries[expr, {x, x0, x1}, n] gives the trigonometric series
	expansion of expr to order n.
*)
(*
  FourierTrigSeries[expr, t, k] finds the Fourier trigonometric coefficients
  c[0], ... c[k], d[1], ..., d[k], for the periodic function of t that is equal
  to expr for -1/2 <= t <= 1/2, repeating with period 1, and gives
  c[0] + Sum[c[n] Cos[2 Pi n t] + d[n] Sin[2 Pi n t], {n, 1, k}], the 
  kth order Fourier trigonometric series approximation to the function.
  FourierTrigSeries[expr, t, k, FourierParameters -> {a, b}] gives 
  Abs[b]^((1+a)/2) (c[0] +
  Sum[c[n] Cos[2 Pi b n t] + d[n] Sin[2 Pi b n t], {n, 1, k}]), the kth order
  Fourier trigonometric series approximation to the periodic function of t that
  is equal to expr for -1/(2 Abs[b]) <= t <= 1/(2 Abs[b]), repeating with period
  1/Abs[b]. *)
(* k must be nonnegative integer-valued *)
FourierTrigSeries::usage =
"FourierTrigSeries[expr, t, k] gives the kth order Fourier trigonometric series
approximation to the periodic function of t that is equal to expr for
-1/2 <= t <= 1/2, and has a period of 1.
FourierTrigSeries[expr, t, k, FourierParameters -> {a, b}] gives the kth order
Fourier trigonometric series approximation to the periodic function of t that
is equal to expr for -1/(2 Abs[b]) <= t <= 1/(2 Abs[b]), and has a period of
1/Abs[b]."

Options[FourierCosCoefficient] = Options[FourierSinCoefficient] =
   Options[FourierTrigSeries] =
	Sort[Join[{FourierParameters -> {0, 1}}, Options[Integrate]]]

(*  ================= numeric Fourier Trigonometric Series ================ *)

(* Note: old syntax...
  NFourierSinSeriesCoefficient[expr, {x, x0, x1}, n] gives the numeric value of
  the coefficient of Sin[2Pi n x / (x1-x0)] in the Fourier trigonometric series
  expansion of expr (n > 0).
*)
(*
  NFourierSinCoefficient[expr, t, n] gives the numerical value of the 
  coefficient of Sin[2 Pi n t], n > 0, in the Fourier trigonometric series 
  expansion of the periodic function of t that is equal to expr for
  -1/2 <= t <= 1/2, repeating with period 1, defined by
  NIntegrate[expr Sin[2 Pi n t], {t, -1/2, 1/2}].
  NFourierSinCoefficient[expr, t, n, FourierParameters -> {a, b}] gives
  Abs[b]^((1-a)/2) NIntegrate[expr Sin[2 Pi b n t],
  {t, -1/(2 Abs[b]), 1/(2 Abs[b])}], the numerical value of the coefficient of
  Sin[2 Pi b n t] in the Fourier trigonometric series expansion of the periodic
  function of t that is equal to expr for -1/(2 Abs[b]) <= t <= 1/(2 Abs[b]),
  repeating with period 1/Abs[b]. *)
NFourierSinCoefficient::usage =
"NFourierSinCoefficient[expr, t, n] gives the numerical value of the 
coefficient of Sin[2 Pi n t], n > 0, in the Fourier trigonometric series 
expansion of the periodic function of t that is equal to expr for
-1/2 <= t <= 1/2, and has a period of 1.
NFourierSinCoefficient[expr, t, n, FourierParameters -> {a, b}] gives the 
numerical value of the coefficient of Sin[2 Pi b n t] in the Fourier
trigonometric series expansion of the periodic function of t that is equal to
expr for -1/(2 Abs[b]) <= t <= 1/(2 Abs[b]), and has a period of 1/Abs[b]."

(* Note: old syntax...
  NFourierCosSeriesCoefficient[expr, {x, x0, x1}, n] gives the numeric value of
  the coefficient of Cos[2Pi n x / (x1-x0)] in the Fourier trigometric series
  expansion of expr (n >= 0).
*)
(*
  NFourierCosCoefficient[expr, t, n] gives the numerical value of the
  coefficient of Cos[2 Pi n t], n >= 0, in the Fourier trigonometric series 
  expansion of the periodic function of t that is equal to expr for
  -1/2 <= t <= 1/2, repeating with period 1, defined by
  If[n===0, 1, 2] NIntegrate[expr Cos[2 Pi n t], {t, -1/2, 1/2}].
  NFourierCosCoefficient[expr, t, n, FourierParameters -> {a, b}] gives 
  If[n===0, 1, 2] Abs[b]^((1-a)/2) NIntegrate[expr Cos[2 Pi b n t],
  {t, -1/(2 Abs[b]), 1/(2 Abs[b])}], the numerical value of the coefficient of
  Cos[2 Pi b n t] in the Fourier trigonometric series expansion of the periodic
  function of t that is equal to expr for -1/(2 Abs[b]) <= t <= 1/(2 Abs[b]),
  repeating with period 1/Abs[b]. *)
NFourierCosCoefficient::usage =
"NFourierCosCoefficient[expr, t, n] gives the numerical value of the 
coefficient of Cos[2 Pi n t], n >= 0, in the Fourier trigonometric series 
expansion of the periodic function of t that is equal to expr for
-1/2 <= t <= 1/2, and has a period of 1.
NFourierCosCoefficient[expr, t, n, FourierParameters -> {a, b}]
gives the numerical value of the coefficient of Cos[2 Pi b n t] in the Fourier
trigonometric series expansion of the periodic function of t that is equal to
expr for -1/(2 Abs[b]) <= t <= 1/(2 Abs[b]), and has a period of 1/Abs[b]."

(* Note: old syntax...
  NFourierTrigSeries[expr, {x, x0, x1}, n] gives the approximate trigonometric
  series expansion of expr to order n.
*)
(*
  NFourierTrigSeries[expr, t, k] finds the numerical values of the Fourier
  trigonometric coefficients c[0], ... c[k], d[1], ..., d[k] for the periodic
  function of t that is equal to expr for -1/2 <= t <= 1/2, repeating with 
  period 1, and gives 
  c[0] + Sum[c[n] Cos[2 Pi n t] + d[n] Sin[2 Pi n t], {n, 1, k}], the kth
  order Fourier trigonometric series approximation to the function.
  NFourierTrigSeries[expr, t, k, FourierParameters -> {a, b}] gives 
  Abs[b]^((1+a)/2) (c[0] +
  Sum[c[n] Cos[2 Pi b n t] + d[n] Sin[2 Pi b n t], {n, 1, k}]), the kth order
  Fourier trigonometric series approximation to the periodic function of
  t that is equal to expr for -1/(2 Abs[b]) <= t <= 1/(2 Abs[b]), repeating with
  period 1/Abs[b], where the c[n] and d[n] are numerical coefficients. *)
NFourierTrigSeries::usage =
"NFourierTrigSeries[expr, t, k] uses numerical coefficients to give the kth
order Fourier trigonometric series approximation to the periodic function of t
that is equal to expr for -1/2 <= t <= 1/2, and has a period of 1.
NFourierTrigSeries[expr, t, k, FourierParameters -> {a, b}] uses numerical
coefficients to give the kth order Fourier trigonometric series approximation
to the periodic function of t that is equal to expr for
-1/(2 Abs[b]) <= t <= 1/(2 Abs[b]), and has a period 1/Abs[b]."

Options[NFourierCosCoefficient] = Options[NFourierSinCoefficient] =
   Options[NFourierTrigSeries] =
	Sort[Join[{FourierParameters -> {0, 1}}, Options[NIntegrate]]]


(************************************************************************)
Begin["`Private`"]
(************************************************************************)

(* ============== NFourierTransform & NInverseFourierTransform ============= *)


NFourierTransform[expr_, t_Symbol, w_, opts___?OptionQ] := 
  Module[{ffcases, focases, a, b, optNInt},
   (
    ffcases = Cases[{opts}, FourierFrequencyConstant -> _];
    If[ffcases =!= {}, Message[NFourierTransform::ffobs]];
    focases = Cases[{opts}, FourierOverallConstant -> _];
    If[focases =!= {}, Message[NFourierTransform::foobs]];
    optNInt = FilterOptions[NIntegrate, opts];
    (* NOTE: the pre-V4.0 FourierOverallConstant corresponds to
	 Sqrt[Abs[b]/(2 Pi)^(1-a)] *)
    Sqrt[Abs[b]/(2 Pi)^(1-a)] NIntegrate[Evaluate[expr Exp[I b w t]],
		{t, -Infinity, Infinity}, Evaluate[optNInt]]
   ) /; ({a, b} = FourierParameters /. {opts} /. Options[NFourierTransform];
	 If[NumberQ[N[b]],
	    True,
	    Message[NFourierTransform::fparm]; False]
	)
  ] /; NumberQ[N[w]] && FreeQ[N[w], Complex]

NInverseFourierTransform[expr_, w_Symbol, t_, opts___?OptionQ] := 
  Module[{ffcases, focases, a, b, optNInt},
   (
    ffcases = Cases[{opts}, FourierFrequencyConstant -> _];
    If[ffcases =!= {}, NFourierTransform::ffobs];
    focases = Cases[{opts}, FourierOverallConstant -> _];
    If[focases =!= {}, NFourierTransform::foobs];
    optNInt = FilterOptions[NIntegrate, opts];
    Sqrt[Abs[b]/(2 Pi)^(1+a)] NIntegrate[Evaluate[expr Exp[-I b w t]],
		{w, -Infinity, Infinity}, Evaluate[optNInt]]
   ) /; ({a, b} = FourierParameters /. {opts} /.
		 Options[NInverseFourierTransform];
	 If[NumberQ[N[b]],
            True,
            Message[NInverseFourierTransform::fparm]; False]
        )
  ] /; NumberQ[N[t]] && FreeQ[N[t], Complex]


(* ============== NFourierSinTransform & NInverseFourierSinTransform ======= *)

NFourierSinTransform[expr_, t_Symbol, w_, opts___?OptionQ] := 
  Module[{ffcases, focases, a, b, optNInt},
   (
    ffcases = Cases[{opts}, FourierFrequencyConstant -> _];
    If[ffcases =!= {}, NFourierSinTransform::ffobs];
    focases = Cases[{opts}, FourierOverallConstant -> _];
    If[focases =!= {}, NFourierSinTransform::foobs];
    optNInt = FilterOptions[NIntegrate, opts];
    (* NOTE: the pre-V4.0 FourierOverallConstant corresponds to
         2 Sqrt[Abs[b]/(2 Pi)^(1-a)] *)
    2 Sqrt[Abs[b]/(2 Pi)^(1-a)] NIntegrate[Evaluate[expr Sin[b w t]],
		{t, 0, Infinity}, Evaluate[optNInt]]
   ) /; ({a, b} = FourierParameters /. {opts} /. Options[NFourierSinTransform];
	 If[NumberQ[N[b]],
            True,
            Message[NFourierSinTransform::fparm]; False]
	)
  ] /; NumberQ[N[w]] && FreeQ[N[w], Complex]

NInverseFourierSinTransform[expr_, w_Symbol, t_, opts___?OptionQ] := 
  Module[{ffcases, focases, a, b, optNInt},
   (
    ffcases = Cases[{opts}, FourierFrequencyConstant -> _];
    If[ffcases =!= {}, NFourierTransform::ffobs];
    focases = Cases[{opts}, FourierOverallConstant -> _];
    If[focases =!= {}, NFourierTransform::foobs];
    optNInt = FilterOptions[NIntegrate, opts];
    2 Sqrt[Abs[b]/(2 Pi)^(1+a)] NIntegrate[Evaluate[expr Sin[b w t]],
		{w, 0, Infinity}, Evaluate[optNInt]]
   ) /; ({a, b} = FourierParameters /. {opts} /.
         		Options[NInverseFourierSinTransform];
	 If[NumberQ[N[b]],
            True,
            Message[NInverseFourierSinTransform::fparm]; False]
        )
  ] /; NumberQ[N[t]] && FreeQ[N[t], Complex]


(* ============== NFourierCosTransform & NInverseFourierCosTransform ======= *)

NFourierCosTransform[expr_, t_Symbol, w_, opts___?OptionQ] := 
  Module[{ffcases, focases, a, b, optNInt},
    ffcases = Cases[{opts}, FourierFrequencyConstant -> _];
    If[ffcases =!= {}, NFourierCosTransform::ffobs];
    focases = Cases[{opts}, FourierOverallConstant -> _];
    If[focases =!= {}, NFourierCosTransform::foobs];
    {a, b} = FourierParameters /. {opts} /. Options[NFourierCosTransform];
    optNInt = FilterOptions[NIntegrate, opts];
    2 Sqrt[Abs[b]/(2 Pi)^(1-a)] NIntegrate[Evaluate[expr Cos[b w t]],
		{t, 0, Infinity}, Evaluate[optNInt]]
  ] /; NumberQ[N[w]] && FreeQ[N[w], Complex]

NInverseFourierCosTransform[expr_, w_Symbol, t_, opts___?OptionQ] := 
  Module[{ffcases, focases, a, b, optNInt},
    ffcases = Cases[{opts}, FourierFrequencyConstant -> _];
    If[ffcases =!= {}, NFourierTransform::ffobs];
    focases = Cases[{opts}, FourierOverallConstant -> _];
    If[focases =!= {}, NFourierTransform::foobs];
    {a, b} = FourierParameters /. {opts} /.
	 Options[NInverseFourierCosTransform];
    optNInt = FilterOptions[NIntegrate, opts];
    2 Sqrt[Abs[b]/(2 Pi)^(1+a)] NIntegrate[Evaluate[expr Cos[b w t]],
		{w, 0, Infinity}, Evaluate[optNInt]]
  ] /; NumberQ[N[t]] && FreeQ[N[t], Complex]


(* =============================== Messages ============================== *)
(* for NFourierTransform, NInverseFourierTransform, NFourierSinTransform,  *)
(* NInverseFourierSinTransform, NFourierCosTransform, and		   *)
(* NInverseFourierCosTransform. *)

NFourierTransform::ffobs = NInverseFourierTransform::ffobs =
NFourierSinTransform::ffobs = NInverseFourierSinTransform::ffobs =
NFourierCosTransform::ffobs = NInverseFourierCosTransform::ffobs =
"FourierFrequencyConstant is an obsolete symbol, superceded by the
constant b in the option setting FourierParameters -> {a, b}."

NFourierTransform::foobs = NInverseFourierTransform::foobs =
"FourierOverallConstant is is an obsolete symbol, superceded by the expression
Sqrt[Abs[b] (2 Pi)^(a-1)] given the option setting FourierParameters -> {a, b}."

NFourierSinTransform::foobs = NFourierCosTransform::foobs =
NInverseFourierSinTransform::foobs = NInverseFourierCosTransform::foobs =
"FourierOverallConstant is is an obsolete symbol, superceded by the expression
2 Sqrt[Abs[b] (2 Pi)^(a-1)] given the option setting
FourierParameters -> {a, b}."

NFourierTransform::fparm = NInverseFourierTransform::fparm =
NFourierSinTransform::fparm = NInverseFourierSinTransform::fparm =
NFourierCosTransform::fparm = NInverseFourierCosTransform::fparm =
"The option setting FourierParameters -> {a, b} must specify numeric b."

(* ============================ Obsolete Forms =========================== *)
(* obsolete forms *)
General::fobslt =
"`1` is an obsolete function superceded by `2`. The new version is
symmetric about the origin, and designed to be consistent with the
transform functions. It should be used with the FourierParameters
option to adjust the period.";

(* These definitions generate error messages when any of several obsolete
   forms are employed *)
FourierSinSeriesCoefficient[any___] := $$dummy/;
    (Message[FourierSinSeriesCoefficient::fobslt,
        FourierSinSeriesCoefficient, FourierSinCoefficient];
     False)

FourierCosSeriesCoefficient[any___] := $$dummy/;
    (Message[FourierCosSeriesCoefficient::fobslt,
        FourierCosSeriesCoefficient, FourierCosCoefficient];
     False)

FourierExpSeriesCoefficient[any___] := $$dummy/;
    (Message[FourierExpSeriesCoefficient::fobslt,
        FourierExpSeriesCoefficient, FourierCoefficient];
     False)

FourierExpSeries[any___] := $$dummy/;
    (Message[FourierExpSeries::fobslt,
        FourierExpSeries, FourierSeries];
     False)

FourierTrigSeries[_, _List, ___] := $$dummy/;
    (Message[FourierTrigSeries::fobslt,
         "FourierTrigSeries[f, {x, x0, x1}, n]",
         "FourierTrigSeries[f, t, k]"];
     False)

NFourierSinSeriesCoefficient[any___] := $$dummy/;
    (Message[NFourierSinSeriesCoefficient::fobslt,
        NFourierSinSeriesCoefficient, NFourierSinCoefficient];
     False)

NFourierCosSeriesCoefficient[any___] := $$dummy/;
    (Message[NFourierCosSeriesCoefficient::fobslt,
        NFourierCosSeriesCoefficient, NFourierCosCoefficient];
     False)

NFourierExpSeriesCoefficient[any___] := $$dummy/;
    (Message[NFourierExpSeriesCoefficient::fobslt,
        NFourierExpSeriesCoefficient, NFourierCoefficient];
     False)

NFourierExpSeries[any___] := $$dummy/;
    (Message[NFourierExpSeries::fobslt,
        NFourierExpSeries, NFourierSeries];
     False)

NFourierTrigSeries[_, _List, ___] := $$dummy/;
    (Message[NFourierTrigSeries::fobslt,
         "NFourierTrigSeries[f, {x, x0, x1}, n]",
         "NFourierTrigSeries[f, t, k]"];
     False)

(* =================== discrete-time Fourier Transform ===================== *)
(* 			(continuous frequency)				     *)

(* w may be symbolic or real *)
DTFourierTransform[expr_, n_Symbol, w_, opts___?OptionQ] := 
  Module[{a, b},
    {a, b} = FourierParameters /. {opts} /. Options[DTFourierTransform];
    (* NOTE:
	When Sum takes options, allow them to be passed from
	DTFourierTransform to Sum. *)
    (* NOTE:
	When Sum takes Assumptions, add Assumptions -> {Element[w, Reals]}. *)
    Abs[b]^((1-a)/2) Sum[Evaluate[expr Exp[2 Pi I b n w]],
					 {n, -Infinity, Infinity}]
  ] /; !NumberQ[N[w]] || FreeQ[N[w], Complex]

(* Note:  separate rules for InverseDTFourierTransform for n symbolic and
        n integer-valued because Assumptions -> {True} is annoying if
        it is not needed.
*)

(* n symbolic *)
InverseDTFourierTransform[expr_, w_Symbol, n_, opts___?OptionQ] := 
  Module[{a, b, optInt},
    {a, b} = FourierParameters /. {opts} /.
                 Options[InverseDTFourierTransform];
    optInt = FilterOptions[Integrate, opts];
    Abs[b]^((1+a)/2) Integrate[expr Exp[-2 Pi I b n w],
		{w, -1/(2 Abs[b]), 1/(2 Abs[b])},
		 Assumptions -> {Element[n, Integers]}, Evaluate[optInt]]
  ] /; !NumberQ[N[n]]


(* n integer-valued *)
InverseDTFourierTransform[expr_, w_Symbol, n_?IntegerQ, opts___?OptionQ] := 
  Module[{a, b, optInt},
    {a, b} = FourierParameters /. {opts} /.
                 Options[InverseDTFourierTransform];
    optInt = FilterOptions[Integrate, opts];
    Abs[b]^((1+a)/2) Integrate[expr Exp[-2 Pi I b n w],
		{w, -1/(2 Abs[b]), 1/(2 Abs[b])}, Evaluate[optInt]]
  ]



(* =============== numeric discrete-time Fourier Transform ================= *)
(* 			(continuous frequency)				     *)

(* w must be real *)
NDTFourierTransform[expr_, n_Symbol, w_, opts___?OptionQ] := 
  Module[{a, b, optNSum},
   (
    optNSum = FilterOptions[NSum, opts];
    Abs[b]^((1-a)/2) NSum[Evaluate[expr Exp[2 Pi I b n w]],
			 {n, -Infinity, Infinity}, Evaluate[optNSum]]
   ) /; ({a, b} = FourierParameters /. {opts} /. Options[NDTFourierTransform];
	 If[NumberQ[N[b]], 
	    True,
	    Message[NDTFourierTransform::fparm]; False]
	)
  ] /; NumberQ[N[w]] && FreeQ[N[w], Complex]

(* n must be integer-valued *)
NInverseDTFourierTransform[expr_, w_Symbol, n_?IntegerQ, opts___?OptionQ] := 
  Module[{a, b, optNInt},
   (
    optNInt = FilterOptions[NIntegrate, opts];
    Abs[b]^((1+a)/2) NIntegrate[Evaluate[expr Exp[-2 Pi I b n w]],
		 Evaluate[{w, -1/(2 Abs[b]), 1/(2 Abs[b])}], Evaluate[optNInt]]
   ) /; ({a, b} = FourierParameters /. {opts} /.
                 Options[NInverseDTFourierTransform];
	 If[NumberQ[N[b]], 
            True,
            Message[NInverseDTFourierTransform::fparm]; False]
	)
  ]

NDTFourierTransform::fparm = NInverseDTFourierTransform::fparm =
"The option setting FourierParameters -> {a, b} must specify numeric b."


(* ================ (discrete-frequency) Fourier Coefficient ============== *)
(* 			(continuous time)				    *)

(* Note:  separate rules for FourierCoefficient for n symbolic and
	n integer-valued because Assumptions -> {True} is annoying if
	it is not needed.
*)

(* n symbolic *)
FourierCoefficient[expr_, t_Symbol, n_, opts___?OptionQ] := 
  Module[{a, b, optInt},
    optInt = FilterOptions[Integrate, opts];
    {a, b} = FourierParameters /. {opts} /. Options[FourierCoefficient];
    Abs[b]^((1-a)/2) Integrate[expr Exp[2 Pi I b n t],
		{t, -1/(2 Abs[b]), 1/(2 Abs[b])},
		 Assumptions -> {Element[n, Integers]}, Evaluate[optInt]]
  ] /; !NumberQ[N[n]]

(* n integer-valued *)
FourierCoefficient[expr_, t_Symbol, n_?IntegerQ, opts___?OptionQ] := 
  Module[{a, b, optInt},
    optInt = FilterOptions[Integrate, opts];
    {a, b} = FourierParameters /. {opts} /. Options[FourierCoefficient];
    Abs[b]^((1-a)/2) Integrate[expr Exp[2 Pi I b n t],
		{t, -1/(2 Abs[b]), 1/(2 Abs[b])}, Evaluate[optInt]]
  ] 

(* t may be symbolic or real *)
InverseFourierCoefficient[expr_, n_Symbol, t_, opts___?OptionQ] := 
  Module[{a, b},
    {a, b} = FourierParameters /. {opts} /. Options[InverseFourierCoefficient];
    (* NOTE:
	When Sum takes options, allow them to be passed from
	InverseFourierCoefficient to Sum. *)
    (* NOTE:
	When Sum takes Assumptions, add Assumptions -> {Element[w, Reals]}. *)
    Abs[b]^((1+a)/2) Sum[Evaluate[expr Exp[-2 Pi I b n t]],
						 {n, -Infinity, Infinity}]
  ]


(* ============ numeric (discrete-frequency) Fourier Coefficient ========== *)
(* 			(continuous time)				    *)

(* n must be integer-valued *)
NFourierCoefficient[expr_, t_Symbol, n_?IntegerQ, opts___?OptionQ] := 
  Module[{a, b, optNInt},
   (
    optNInt = FilterOptions[NIntegrate, opts];
    Abs[b]^((1-a)/2) NIntegrate[Evaluate[expr Exp[2 Pi I b n t]],
		Evaluate[{t, -1/(2 Abs[b]), 1/(2 Abs[b])}], Evaluate[optNInt]]
   ) /; ({a, b} = FourierParameters /. {opts} /.
                         Options[NFourierCoefficient];
         If[NumberQ[N[b]],
            True,
            Message[NFourierCoefficient::fparm]; False]
        )
  ]

(* t must be real *)
NInverseFourierCoefficient[expr_, n_Symbol, t_, opts___?OptionQ] := 
  Module[{a, b, optNSum},
   (
    optNSum = FilterOptions[NSum, opts];
    Abs[b]^((1+a)/2) NSum[Evaluate[expr Exp[-2 Pi I b n t]],
			 {n, -Infinity, Infinity}, Evaluate[optNSum]]
   ) /; ({a, b} = FourierParameters /. {opts} /.
			 Options[NInverseFourierCoefficient];
	 If[NumberQ[N[b]],
	    True,
            Message[NInverseFourierCoefficient::fparm]; False]
	)
  ] /; NumberQ[N[t]] && FreeQ[N[t], Complex]

NFourierCoefficient::fparm = NInverseFourierCoefficient::fparm =
"The option setting FourierParameters -> {a, b} must specify numeric b."

(* ========================= Fourier series ========================= *)
(* 	based on kth-order approximation using FourierCoefficient     *)

FourierSeries[expr_, t_, k_?IntegerQ, opts___?OptionQ] :=
  Module[{a, b, table, optFourC},
     {a, b} = FourierParameters /. {opts} /. Options[FourierSeries];
     optFourC = FilterOptions[FourierCoefficient, opts];
     table = Table[Exp[-2 Pi I b n t] *
		FourierCoefficient[expr, t, n, optFourC],
							{n, -k, k}];
     Abs[b]^((1+a)/2) Apply[Plus, table]
  ] /; k >= 0

(* ====================== numeric Fourier series ===================== *)
(* 	based on kth-order approximation using NFourierCoefficient     *)

NFourierSeries[expr_, t_, k_?IntegerQ, opts___?OptionQ] :=
  Module[{a, b, table, optNFourC},
   (
     optNFourC = FilterOptions[NFourierCoefficient, opts];
     table = Table[Exp[-2 Pi I b n t] *
		NFourierCoefficient[expr, t, n, optNFourC],
							{n, -k, k}];
     Abs[b]^((1+a)/2) Apply[Plus, table]
   ) /; (
         {a, b} = FourierParameters /. {opts} /. Options[NFourierSeries];
	 If[NumberQ[N[b]],
            True,
            Message[NFourierSeries::fparm]; False]
        )
  ] /; k >= 0

NFourierSeries::fparm =
"The option setting FourierParameters -> {a, b} must specify numeric b."


(* ============== (discrete-frequency) Fourier Cos Coefficient ============ *)
(* 			(continuous time)				    *)

(* Note:  separate rules for FourierCosCoefficient for n symbolic and
        n integer-valued because Assumptions -> {True} is messy if
        it is not needed.
*)

(* n symbolic *)
FourierCosCoefficient[expr_, t_Symbol, n_, opts___?OptionQ] := 
  Module[{a, b, optInt},
    optInt = FilterOptions[Integrate, opts];
    {a, b} = FourierParameters /. {opts} /. Options[FourierCosCoefficient];
    If[n===0, 1, 2] Abs[b]^((1-a)/2) Integrate[expr Cos[2 Pi b n t],
		{t, -1/(2 Abs[b]), 1/(2 Abs[b])}, 
		Assumptions -> {Element[n, Integers], n >= 0},
		Evaluate[optInt]]
  ] /; !NumberQ[N[n]]


(* n nonnegative integer-valued (i.e., n = 0, 1, 2, ...) *)
FourierCosCoefficient[expr_, t_Symbol, n_?IntegerQ, opts___?OptionQ] := 
  Module[{a, b, optInt},
    optInt = FilterOptions[Integrate, opts];
    {a, b} = FourierParameters /. {opts} /. Options[FourierCosCoefficient];
    If[n===0, 1, 2] Abs[b]^((1-a)/2) Integrate[expr Cos[2 Pi b n t],
		{t, -1/(2 Abs[b]), 1/(2 Abs[b])}, Evaluate[optInt]] 
  ] /; n >= 0


(* ============== (discrete-frequency) Fourier Sin Coefficient ============ *)
(* 			(continuous time)				    *)

(* Note:  separate rules for FourierCosCoefficient for n symbolic and
        n integer-valued because Assumptions -> {True} is messy if
        it is not needed.
*)

(* n symbolic *)
FourierSinCoefficient[expr_, t_Symbol, n_, opts___?OptionQ] := 
  Module[{a, b, optInt},
    optInt = FilterOptions[Integrate, opts];
    {a, b} = FourierParameters /. {opts} /. Options[FourierSinCoefficient];
    2 Abs[b]^((1-a)/2) Integrate[expr Sin[2 Pi b n t],
		{t, -1/(2 Abs[b]), 1/(2 Abs[b])},
		 Assumptions -> {Element[n, Integers], n >= 1},
		Evaluate[optInt]]
  ] /; !NumberQ[N[n]]


(* n positive integer-valued (i.e., n = 1, 2, ...) *)
FourierSinCoefficient[expr_, t_Symbol, n_?IntegerQ, opts___?OptionQ] := 
  Module[{a, b, optInt},
    optInt = FilterOptions[Integrate, opts];
    {a, b} = FourierParameters /. {opts} /. Options[FourierSinCoefficient];
    2 Abs[b]^((1-a)/2) Integrate[expr Sin[2 Pi b n t],
		{t, -1/(2 Abs[b]), 1/(2 Abs[b])},
		Evaluate[optInt]]
  ] /; n >= 1


(* ========== numeric (discrete-frequency) Fourier Cos Coefficient ======== *)
(* 			(continuous time)				    *)

(* n must be nonnegative integer-valued (i.e., n = 0, 1, 2, ...) *)
NFourierCosCoefficient[expr_, t_Symbol, n_?IntegerQ, opts___?OptionQ] := 
  Module[{a, b, optNInt},
   (
    optNInt = FilterOptions[NIntegrate, opts];
    If[n===0, 1, 2] Abs[b]^((1-a)/2) NIntegrate[Evaluate[expr Cos[2 Pi b n t]],
		Evaluate[{t, -1/(2 Abs[b]), 1/(2 Abs[b])}], Evaluate[optNInt]]
   ) /; ({a, b} = FourierParameters /.
		 {opts} /. Options[NFourierCosCoefficient];
	 If[NumberQ[N[b]],
            True,
            Message[NFourierCosCoefficient::fparm]; False]
	)
  ] /; n >= 0

NFourierCosCoefficient::fparm =
"The setting FourierParameters -> {a, b} must specify numeric b."




(* ========== numeric (discrete-frequency) Fourier Sin Coefficient ======== *)
(* 			(continuous time)				    *)

(* n must be positive integer-valued (i.e., n = 1, 2, ...) *)
NFourierSinCoefficient[expr_, t_Symbol, n_?IntegerQ, opts___?OptionQ] := 
  Module[{a, b, optNInt},
   (
    optNInt = FilterOptions[NIntegrate, opts];
    2 Abs[b]^((1-a)/2) NIntegrate[Evaluate[expr Sin[2 Pi b n t]],
		Evaluate[{t, -1/(2 Abs[b]), 1/(2 Abs[b])}], Evaluate[optNInt]]
   ) /; ({a, b} = FourierParameters /.
		 {opts} /. Options[NFourierSinCoefficient];
	 If[NumberQ[N[b]],
            True,
            Message[NFourierSinCoefficient::fparm]; False]
	)
  ] /; n >= 1

NFourierSinCoefficient::fparm =
"The setting FourierParameters -> {a, b} must specify numeric b."



(* ===================== Fourier trigonometric series ===================== *)
(* 	based on kth-order approximation using				*)
(*	 FourierSinCoefficient and FourierCosCoefficient.     		*)

FourierTrigSeries[expr_, t_Symbol, k_?IntegerQ, opts___?OptionQ] :=
  Module[{a, b, table, optFourC},
    optFourC = FilterOptions[FourierCosCoefficient, opts];
    {a, b} = FourierParameters /. {opts} /. Options[FourierTrigSeries];
    table = Table[Cos[2 Pi b n t] FourierCosCoefficient[expr, t, n, optFourC] + 
		  Sin[2 Pi b n t] FourierSinCoefficient[expr, t, n, optFourC],
	 			{n, 1, k}];  
    Abs[b]^((1+a)/2) (
       FourierCosCoefficient[expr, t, 0, optFourC] + Apply[Plus, table]
			)
  ] /; k >= 0

(* ===================== Fourier trigonometric series ===================== *)
(* 	based on kth-order approximation using				*)
(*	 NFourierSinCoefficient and NFourierCosCoefficient.    		*)


NFourierTrigSeries[expr_, t_Symbol, k_?IntegerQ, opts___?OptionQ] :=
  Module[{a, b, table, optNFourC},
   (
    optNFourC = FilterOptions[NFourierCosCoefficient, opts];
    table = Table[Cos[2 Pi b n t]NFourierCosCoefficient[expr, t, n, optNFourC] +
		  Sin[2 Pi b n t]NFourierSinCoefficient[expr, t, n, optNFourC],
				{n, 1, k}];
    Abs[b]^((1+a)/2) (
       NFourierCosCoefficient[expr, t, 0, optNFourC] + Apply[Plus, table]
		        )
   ) /; ({a, b} = FourierParameters /. {opts} /. Options[NFourierTrigSeries];
	 If[NumberQ[N[b]],
            True,
            Message[NFourierTrigSeries::fparm]; False]
        )
  ] /; k >= 0

NFourierTrigSeries::fparm =
"The setting FourierParameters -> {a, b} must specify numeric b."


(************************************************************************)
End[]             (* end `Private` Context                              *)
(************************************************************************)
 
 
 
(************************************************************************)
EndPackage[]      (* end package Context                                *)
(************************************************************************)




