7
$\begingroup$

There is an attribute NumericFunction in Mathematica that can do the following job:

Attributes[f] = {NumericFunction};
NumericQ[f[1,2,3,4]]

then returns true. However, the following return false

NumericQ[f[{1,2,3,4}]]; NumericQ[f[1,{2},3,{4}]]

which makes sense by Documentation on NumericFunction. However, I want to define a function $f$ that returns True even in above cases, how can this be achieved?

Curiously, functions like HypergeometricPFQ has Attributes NumericFunction, but NumericQ[HypergeometricPFQ[{1, Sqrt[2]}, {Pi}, 1/3]] still returns true despite having lists in its arguments, why?

My goal is to define an f such that all expressions like f[1,{2},3,{4}], 1+5*f[1,{2},3,{4}], Sin[1+5*f[1,{2},3,{4}]] returns true upon NumericQ. How can this be done?

Thank you.


Update: After much thoughts, I think I found a solution:

SetAttributes[f, NumericFunction]; Unprotect[NumericQ];
$numericflag = 0; 
NumericQ[expr_] /; FreeQ[expr, f] == False && $numericflag == 0 := 
 Block[{bool}, $numericflag = 1; 
  bool = NumericQ[expr /. f[x__] :> f @@ Flatten[{x}]]; $numericflag =
    0; Return[bool]]; Protect[NumericQ];

it works as expected: NumericQ[Pi + 58 + f[2, 3, {4, 4}]], NumericQ[Sin[f[2,{3,{0,0}}]]] all return true.

$\endgroup$
2
  • 2
    $\begingroup$ I don't have a rigorous answer, but it appears that it is linked to the fact f is not defined. If you define f (e.g. f[l___]:=1 the result of NumericQ@f[{1},2,3] become True $\endgroup$
    – youyou
    May 14, 2020 at 13:21
  • 4
    $\begingroup$ @youyou Isn't it because f evaluates to 1 first? NumericQ doesn't have any Hold* attributes. $\endgroup$
    – swish
    May 14, 2020 at 15:27

2 Answers 2

2
$\begingroup$

I thought @swish would incorporate my comment, but let me put it here, since it is an answer to the question. In the following, the arguments of f can be numbers or any sort of nested lists of numbers.

f /: NumericQ[f[args___]] /; VectorQ[Flatten@{args}, NumericQ] := True;

NumericQ[f[1, 2, 3, 4]]
NumericQ[f[{1, 2, 3, 4}]]
NumericQ[f[1, {2}, 3, {4}]]
NumericQ[f[x]]  (* False -- should check both cases T, F *)
NumericQ[f[]]   (* True  -- same as `NumericQ[Sin[]]` *)
(*
  True
  True
  True
  False
  True
*)

Update

@pisco points out that the above does not work if f[..] is nested inside other numeric expressions. There is an internal function that could be used to replace NumericQ:

ClearAll[f];
Attributes@f = {NumericFunction};

Internal`WouldBeNumericQ[2 + f[1, {2}, 3], {}]
(*  True  *)

The last list is a list a variables, the function tests whether f would be numeric if numeric values were substituted for the variables.

$\endgroup$
2
  • $\begingroup$ Thank you for your answer. However, one major shortcoming seems that NumericQ[1+f[1,2,3]] returns false. If one sets NumericFunction attributes to f, this returns true. However, NumericQ[1+f[1,{2},3]] still returns false. How to tackle this? $\endgroup$
    – pisco
    May 28, 2020 at 5:43
  • 1
    $\begingroup$ @pisco I added a workaround to my answer. Feel free to unaccept if it's not satisfactory. The workings of NumericQ are hidden from Trace. I suspect there are some optimizations in C that get around my first def. $\endgroup$
    – Michael E2
    May 28, 2020 at 13:16
2
$\begingroup$

There is a slight problem with NumericQ, that prevents one to define your UpValues with it. So that would not work as expected:

f /: NumericQ[_f] := True

But manually

UpValues[f] = {HoldPattern[NumericQ[_f]] :> True};

it works as expected:

NumericQ[f[{1, 2, 3, 4}]]
NumericQ[f[1, {2}, 3, {4}]]
(* True *)
(* True *)
$\endgroup$
1
  • 2
    $\begingroup$ I think the solution is a little over-eager :) -- Try NumericQ[f[1, {2, t}, 4]] which should return False. I think the def. f /: NumericQ[f[args___]] /; VectorQ[Flatten@{args}, NumericQ] := True is more on-target. $\endgroup$
    – Michael E2
    May 14, 2020 at 17:33

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.