# How to get Series to recognize user-defined function has pole

Edit for clarity: How does Mathematica's function Series know that Gamma[x] has a pole at x=0? When Series is called to expand near x=0, it gives the proper 1/x term in its Laurent expansion. I need to copy this behavior of Series to user-defined functions.

Series[Gamma[x],{x,0,1}]


1/x-EulerGamma+1/12 (6 EulerGamma^2+[Pi]^2) x+O[x]^2

In the package I'm writing I have several complicated functions that have simple poles near isolated points. These functions are to be evaluated only when its arguments are numerical. Otherwise, for the sake of brevity of the output, these functions remain unevaluated and is supposed to act like a special function.

Simple example: $$f(x) = \frac{\cos(x)}{x}$$

Task: I would like to be able to carry out a Series expansion in $x$; especially around $x=0$ where it should yield the $1/x$ pole term in the Laurent series:

Here is what I did:

SetAttributes[f,NumericFunction];
f[x_?NumericQ] := 1/x Cos[x];
Derivative[n_][f][x_] := Derivative[n][1/# Cos[#] &][x];


So now, I test this, and try to obtain the expansion near $x=\pi/2$.

Series[f[x], {x, Pi/2, 2}] which works, but around $x=0$,

Series[f[x], {x, 0, 2}] I get an error. So, how can I tell Series that at $x=0$, the function f starts at $1/x$? I need Series to behave just as it would if I gave it the full functional form explicitly:

Series[1/x Cos[x], {x, 0, 2}] • Sorry, am error. Sep 29, 2014 at 11:15
• The example of 1/x Cos[x] is just a simple example. In the application I'm developing, the expression is substantially more complicated. I would rather let f[x] be an abbreviation for this complicated analytic expression, and let users be able work with f instead of the complicated expression. Sep 29, 2014 at 11:18
• Have you tried using Hold and ReleaseHold? Sep 29, 2014 at 13:46
• No, I'm not sure how to use it in this case. Would you demonstrate? Sep 29, 2014 at 14:31
• Is there a reason you define a derivative for f ? Sep 29, 2014 at 16:22

According to David B. Wagner's book, Power Programming with Mathematica (ch 9.3), you can define upvalues for Series. Here's how I implement it:

Clear[f]; ClearAll[f];
SetAttributes[f, NumericFunction]
f[x_?NumericQ] = Cos[x]/x;

(*So that Series works at regular points*)
Derivative[n_][f][x_] := Derivative[n][1/# Cos[#] &][x];

(*Give explicit definition at singular point*)
f /: Series[f[x_], {x_, 0, n_}] := If[n >= -1,
1/x + Series[Cos[x]/x - 1/x, {x, 0, n}], SeriesData[x, 0, List[], -1, -1, 1]];


First, the built-in behavior of Series on an expression is that if the desired order n is lower than the order of the lowest non-vanishing term a of that expression, the output is O[x]^a.

Finally, explicitly give the singular terms in the Series expansion, followed by an explicit instruction to compute the series with the singular parts subtracted.

Unfortunately, this is not robust against expressions containing f[x]:

Series[x*f[x], {x,0,3}]


Power::infy: Infinite expression 1/0^2 encountered.
Power::infy: Infinite expression 1/0 encountered.
Infinity::indet: Indeterminate expression 0 ComplexInfinity encountered.

If you don't mind mucking with internal symbols, you can add the following:

f /: SystemPrivateInternalSeries[f[x_], e_] := Series[Cos[x]/x, e]
f[x_?NumericQ] := Cos[x]/x


Then:

Series[x f[x], {x, 0, 3}] //TeXForm


$1-\frac{x^2}{2}+O\left(x^4\right)$

and:

Series[f[x]/x, {x, 0, 3}] //TeXForm


$\frac{1}{x^2}-\frac{1}{2}+\frac{x^2}{24}+O\left(x^4\right)$

behave the way you want, and f also evaluates as desired:

f[x]
f


f[x]

Cos

• Yes, this is perfect; because now it works like a built-in function. +1 Aug 13, 2018 at 18:34

Given the numerical nature of the definitions, this problem can best be attacked using the NumericalCalculus package:

Needs["NumericalCalculus"]

Chop[Normal[NSeries[f[x], {x, 0, 2}]]]

(* ==> 1.00002/x - 0.5 x *)


To improve the numerical accuracy of the results, you may want to adjust the WorkingPrecision and Radius options depending on the actual function you're trying to expand. See the documentation for NSeries.

• Thanks for the answer, but I'm writing a package that is largely meant for analytic manipulations. I must make the task work for Series and not NSeries. How does Mathematica know that $\Gamma(x)$ has a pole at $x=0$, so that Series starts at 1/x? I need to mimic this effect. Sep 30, 2014 at 10:23
• I have edited my question, and hopefully, it is clearer. Sep 30, 2014 at 10:29
• You reference to Gamma is confusing because it doesn't actually do what you seem to be asking for in the question. E.g., Gamma[1/3] doesn't evaluate even though the argument is numeric. Obviously your question wants that to evaluate, too. So I don't know what the real goal is.
– Jens
Sep 30, 2014 at 21:18
• Ok, the line f[x_?NumericQ]=...` has made the question confusing. I have completely reworded the question mathematica.stackexchange.com/questions/61055/… Oct 1, 2014 at 5:55