6
$\begingroup$

I have been playing a bit with the undocumented function

Experimental`CreateNumericalFunction

and I wanted to know if somebody found a way to make generated numerical functions listable.

Here is an example: I define two functions, f and fC

In[1]:=f = Experimental`CreateNumericalFunction[{x}, x^2, {}, {_Real},WorkingPrecision -> 30];

In[2]:=fC = Compile[{{x, _Real}}, x^2, RuntimeAttributes -> {Listable}];

The first function is not listable, while the second is:

In[3]:=f@Table[i, {i, 1, 10}]
Out[3]:=Experimental`NumericalFunction[{x}, x^2,"-NumericalFunctionData-"][{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}]

In[4]:=fC@Table[i, {i, 1, 10}]
Out[4]:={1., 4., 9., 16., 25., 36., 49., 64., 81., 100.}

Is there a way to make f also listable?

$\endgroup$
4
  • $\begingroup$ What even is Experimental`CreateNumericalFunction? $\endgroup$ Commented Oct 5, 2019 at 4:12
  • 1
    $\begingroup$ Unless I am mistaken, Experimental`CreateNumericalFunction is the closest one can get to compiling a function with arbitrary precision. As far as I can tell, Compile for now only takes Real64 arguments... Something like Real128 is still not available (not sure it will ever be). $\endgroup$ Commented Oct 5, 2019 at 4:20
  • 2
    $\begingroup$ Strongly related: "How to work with Experimental`NumericalFunction?." $\endgroup$ Commented Oct 6, 2019 at 12:44
  • $\begingroup$ One could always wrap it with a Listable function: fL = Function[x, f[x], Listable] $\endgroup$ Commented Oct 6, 2019 at 12:52

1 Answer 1

8
$\begingroup$

I do not know a way to make Experimental`NumericalFunction listable itself, but depending of your goals you can achieve the same behavior in several ways.

The simplest way is to create a proxy Symbol with Listable attribute:

ClearAll[f, fL]
SetAttributes[fL, Listable]
fL[x_] := f[x]
f = Experimental`CreateNumericalFunction[{x}, x^2, {}, {_}, WorkingPrecision -> 30];
fL@Table[i, {i, 1, 10}]
{1.`30., 4.`30., 9.`30., 16.`30., 25.`30., 36.`30., 49.`30., 64.`30., 81.`30., 100.`30.}

It is also possible to assign the Listable attribute directly to f:

ClearAll[f]
SetAttributes[f, Listable]
f[x_] = Block[{x},
  Experimental`CreateNumericalFunction[{x}, x^2, {}, {_Real}, WorkingPrecision -> 30][x]]
f@Table[i, {i, 1, 10}]
{1.`30., 4.`30., 9.`30., 16.`30., 25.`30., 36.`30., 49.`30., 64.`30., 81.`30., 100.`30.}

Instead of the attribute one can program listability via Map what can be even faster:

ClearAll[f]
f[l_List] := f /@ l;
f[x_] = Block[{x},
   Experimental`CreateNumericalFunction[{x}, x^2, {}, {_Real}, WorkingPrecision -> 30][x]];
f@Table[i, {i, 1, 10}]
{1.`30., 4.`30., 9.`30., 16.`30., 25.`30., 36.`30., 49.`30., 64.`30., 81.`30., 100.`30.}

Another way is to create a listable pure function:

ClearAll[f]
f = With[{f = Experimental`CreateNumericalFunction[{x}, x^2, {}, {_Real}, WorkingPrecision -> 30]},
         Function[x, f[x], Listable]];
f@Table[i, {i, 1, 10}]
{1.`30., 4.`30., 9.`30., 16.`30., 25.`30., 36.`30., 49.`30., 64.`30., 81.`30., 100.`30.}

Or you can Map f at level -1 (assuming that your input matrix contains only numbers and not expressions):

ClearAll[f]
f = Experimental`CreateNumericalFunction[{x}, x^2, {}, {_Real}, WorkingPrecision -> 30];
table = Table[i, {i, 1, 10}];
Map[f, table, {-1}]
{1.`30., 4.`30., 9.`30., 16.`30., 25.`30., 36.`30., 49.`30., 64.`30., 81.`30., 100.`30.}

Also it is possible to create a numerical function accepting a list of fixed length (but probably it isn't sufficient for you):

ClearAll[f]
f = Experimental`CreateNumericalFunction[{{x, {10}}}, x^2, {10}, WorkingPrecision -> 30];
f@Table[i, {i, 1, 10}]
{1.`30., 4.`30., 9.`30., 16.`30., 25.`30., 36.`30., 49.`30., 64.`30., 81.`30., 100.`30.}
$\endgroup$
1
  • $\begingroup$ Dear Alexey, in the end the best option for me was to use ``` Map[f,table,{-1}]``` Thanks for all your help! $\endgroup$ Commented Oct 7, 2019 at 13:22

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.