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$
  • $\begingroup$ What even is Experimental`CreateNumericalFunction? $\endgroup$ – QuantumDot Oct 5 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$ – user12588 Oct 5 at 4:20
  • 1
    $\begingroup$ Strongly related: "How to work with Experimental`NumericalFunction?." $\endgroup$ – Alexey Popkov Oct 6 at 12:44
  • $\begingroup$ One could always wrap it with a Listable function: fL = Function[x, f[x], Listable] $\endgroup$ – Michael E2 Oct 6 at 12:52
6
$\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$
  • $\begingroup$ Dear Alexey, in the end the best option for me was to use ``` Map[f,table,{-1}]``` Thanks for all your help! $\endgroup$ – user12588 Oct 7 at 13:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.