# A more convenient Fourier series

Personally, I feel the design of FourierSeries/FourierSinSeries/FourierCosSeries/FourierTrigSeries not convenient enough because:

1. They can't give general formula of series as output, one must set a specific integer as the order of series.

2. One cannot define the domain to be expanded in a convenient way. What if I want to expand a function $f(x)$ in e.g. $x\in(2,10)$?

Can we make them more handy?

For the reasons mentioned above, I wrote the following "shell" for these functions:

(* Weak test for singularity *)
findSingular[coe_, k_, assump___] :=
Piecewise[{{{}, # === k}}, #] &[
k /. Union@Solve[{assump, Denominator@Together@coe == 0, k ∈ Integers}, k]]

generalTerm[expr_, {t_, a_, b_}, n_: C][coefunc_, termfunc_, assump___] :=
With[{generalCoe = coefunc[expr, {t, a, b}, \[FormalK]]},
With[{singularity = findSingular[generalCoe, \[FormalK], assump]},
Piecewise[{{generalCoe, And @@ (\[FormalK] != # & /@ singularity)},
Sequence @@ ({coefunc[expr, {t, a, b}, #], \[FormalK] == #} & /@
singularity)}] termfunc[{t, a, b}, \[FormalK]]]]

summation[lowerbound_, upperbound_] :=
HoldForm@Sum[#, {\[FormalK], lowerbound, upperbound}] &

trans[old_, new_, var_] := First@RescalingTransform[{new}, {old}][{var}]

easyFourierSinCoefficient[expr_, {t_, a_, b_}, k_] :=
FourierSinCoefficient[expr /. t -> trans[{a, b}, {0, Pi}, t], t, k] /.
t -> trans[{0, Pi}, {a, b}, t]

Block[{t, a, b, k},
easySinTerm[{t_, a_, b_}, k_] = Sin[k t] /. t -> trans[{0, Pi}, {a, b}, t] // Simplify];

easyFourierSinSeries[expr_, {t_, a_, b_}, n_: C] :=
summation[1, n]@
generalTerm[expr, {t, a, b}][easyFourierSinCoefficient, easySinTerm, \[FormalK] > 0]

easyFourierCoefficient[expr_, {t_, a_, b_}, k_] :=
FourierCoefficient[expr /. t -> trans[{a, b}, {-Pi, Pi}, t], t, k] /.
t -> trans[{-Pi, Pi}, {a, b}, t]

Block[{t, a, b, k},
easyTerm[{t_, a_, b_}, k_] =
Exp[I k t] /. t -> trans[{-Pi, Pi}, {a, b}, t] // Simplify];

easyFourierSeries[expr_, {t_, a_, b_}, n_: C] :=
summation[-n, n]@
PiecewiseExpand@
Piecewise[{{generalTerm[expr, {t, a, b}][easyFourierCoefficient,
easyTerm], \[FormalK] != 0}},
easyFourierCoefficient[expr, {t, a, b}, 0] easyTerm[{t, a, b}, 0]]

easyFourierCosCoefficient[expr_, {t_, a_, b_}, k_] :=
FourierCosCoefficient[expr /. t -> trans[{a, b}, {0, Pi}, t], t, k] /.
t -> trans[{0, Pi}, {a, b}, t]

Block[{t, a, b, k},
easyCosTerm[{t_, a_, b_}, k_] = Cos[k t] /. t -> trans[{0, Pi}, {a, b}, t] // Simplify];

easyFourierCosSeries[expr_, {t_, a_, b_}, n_: C] :=
easyFourierCosCoefficient[expr, {t, a, b}, 0]/2 +
summation[1, n]@
generalTerm[expr, {t, a, b}][easyFourierCosCoefficient, easyCosTerm, \[FormalK] > 0]

Block[{t, a, b, k},
easyTrigTerm[{t_, a_, b_},
k_] = {Cos[k t], Sin[k t]} /. t -> trans[{-Pi, Pi}, {a, b}, t] // Simplify];

easyFourierTrigSeries[expr_, {t_, a_, b_}, n_: C] :=
easyFourierCoefficient[expr, {t, a, b}, 0] +
summation[1, n]@
Collect[Simplify[
generalTerm[expr, {t, a, b}][easyFourierCoefficient,
ExpToTrig@easyTerm@## &, \[FormalK] !=
0] /. {{\[FormalK] -> \[FormalK]}, {\[FormalK] -> -\[FormalK]}} //
Total, \[FormalK] > 0 && \[FormalK] ∈ Integers], (Cos | Sin)[_]]


I'm still in v9 so choose HoldForm rather than Inactivate to hold Sum.

The usage of these functions are simple and straightforward. For example, suppose I want to expand

$$f(x)=\left\{ \begin{array}{ll} x & -\frac{1}{2}\leq x<0 \\ 1 & 0\leq x<\frac{1}{2} \\ -1 & \frac{1}{2}\leq x<\frac{3}{2} \\ \end{array}\right.$$

in $-\frac{1}{2}<x<\frac{3}{2}$ with Fourier sine series, then I just need to write

expr = Piecewise[{{x, -1/2 <= x < 0}, {1, 0 <= x < 1/2}, {-1, 1/2 <= x < 3/2}}]
series = easyFourierSinSeries[expr, {x, -1/2, 3/2}]


If you want to plot or do numeric calculation with the result, just replace C with a specific integer and ReleaseHold:

Plot[{expr, series /. C -> 24 // ReleaseHold} // Evaluate, {x, -1/2, 3/2},
PlotRange -> All]


• Thanks, the built-in functions are indeed kind of hard to remember so I usually rescale arguments by hand before using them... – Jens Jul 1 '17 at 16:05
• These procedures are really very helpful. Thanks for this work. (+1) – user36273 Jul 2 '17 at 13:22
• Please be careful in handling these procedures! For example: f = Piecewise[{{x Sin[x], 0 <= x <= 2 Pi}}] , series = easyFourierSinSeries[f, {x, 0, 2 Pi}] /. C -> 5 // ReleaseHold – user36273 Jul 2 '17 at 17:51
• @rewi OK, the problem is harder than I expected… The core issue is that we don't have a general function for obtaining singularity (see discussion here for more information). Anyway, I've modified the code to make the shell more general, have a look. – xzczd Jul 2 '17 at 20:21
• Fantastic! The above example is now properly calculated, furthermore, I have also given difficult examples, e.g. Phase control; it works. – user36273 Jul 2 '17 at 21:15

Regarding the above Piecewise[ ] function:

Piecewise[{{x, -1/2 <= x < 0}, {1, 0 <= x < 1/2}, {-1, 1/2 <= x < 3/2}}]


There is another package (FS.m) that can compute the Fourier series of this type of function. It is located at https://arxiv.org/src/0806.0150v3/anc/FS.m (Most of the package was written long before FourierCoefficient[ ], etc. came along).

You can read in the package with something like << "C:\someDir\FS.m"

If all you want is a nicely-formatted expression for the Fourier series, then use formatSeries:

formatSeries[x, {x, 1, -1}, {-1/2, 0, 1/2, 3/2}, n]


If you don't care about the formatting, but instead just want expressions for the coefficients in terms of n, along with a graph of the function and 10 terms of its Fourier series, then use fSeries:

coeffs = fSeries[x, {x, 1, -1}, {-1/2, 0, 1/2, 3/2}, n, 10]


fSeries returns a list of three items:

coeffs = { aZeroOver2 , an , bn }


aZeroOver2 is the constant term; an and bn are the expressions for the nth cosine and sine terms.

I often find it easier to specify piecewise-continuous functions with a list of (x, y) pairs at endpoints, corners, and jumps:

xyPairs = { {-1/2, -1/2}, {0, 0}, {0, 1}, {1/2, 1}, {1/2, -1}, {3/2, -1} }


formatSeries and fSeries can also work with these (x, y) pairs:

formatSeries[x, xyPairs, n]

fSeries[x, xyPairs, n, 10]


In the above example, the period is $p = 3/2 - (-1/2) = 2$, so $2\pi/p = \pi$, so the Fourier series is

a0/2 + Sum[an * Cos[n Pi x] + bn * Sin[n Pi x], {n, 1, Infinity}]


The following plots the sum of 10 terms of the series over a larger interval that includes three periods:

Plot[coeffs[[1]] + Sum[(coeffs[[2]])*Cos[n Pi x] + (coeffs[[3]])*Sin[n Pi x], {n, 1, 10}], {x, -1/2 - 2, 3/2 + 2}]

• Happy to see another answer! Then, I think it's worth pointing out that 1. formatSeries can actually handle Piecewise directly, one just needs to make the second argument a List: formatSeries[x, List@Piecewise[{{x, -1/2 <= x < 0}, {1, 0 <= x < 1/2}, {-1, 1/2 <= x < 3/2}}] , {-1/2, 3/2}, n] (Well, I think this design isn't that convenient and can be improved.) 2. This package currently has trouble in handling some edge cases e.g. formatSeries[x, {x Sin[x]}, {0, 2 Pi}, n] – xzczd Jul 19 '17 at 4:19