# What is the most effective method of making function which should be different for real and integer arguments?

Which of the following 2 methods is better for heavy serial calculations?

Method 1:

f[x_Integer]:=Module[{...}, ...]
f[x_Real]:=Module[{...}, ...]


Method 2:

f[x_]:=Module[{...}, ...
, ...
, ...
]
]


Does this help?:

f1[x_Integer] := x^3;
f1[x_Real] := x^3;

f2[x_] := If[Head[x] === Integer, x^3, x^3];

f3[x_] := If[MatchQ[x, _Integer], x^3, x^3];

input = {RandomInteger[10, 10^5], RandomReal[1, 10^5]};

Map[f1, input, {2}]; // AbsoluteTiming
Map[f2, input, {2}]; // AbsoluteTiming
Map[f3, input, {2}]; // AbsoluteTiming
(*
{0.165381, Null}
{0.327146, Null}
{0.306359, Null}
*)

• I might add that if the body of the function takes a significant amount of time to execute, say, more than $10^{-5}$ or $10^{-4}$ seconds, then the difference above won't matter that much. It might be more important to choose which method is clearer to understand, easier to maintain, and perhaps simpler to program. Feb 7 '18 at 14:47

If you plan to map your function over PackedArrays and if the body is vectorized then it might be better to perform only one check in the beginning at let loose the vectorization:

f1[x_Integer] := x^3;
f1[x_Real] := x^2;

PackedIntegerArrayQ[x_] := DeveloperPackedArrayQ[x, Integer];
PackedRealArrayQ[x_] := DeveloperPackedArrayQ[x, Real];

f4[x_?PackedIntegerArrayQ] := x^3;
f4[x_?PackedRealArrayQ] := x^2;


Now the test:

input = {RandomInteger[10, 10^5], RandomReal[1, 10^5]};
output1 = Map[f1, input, {2}]; // AbsoluteTiming // First
output2 = f4 /@ input; // AbsoluteTiming // First
output1 == output2


0.138853

0.000536

True

• You can use DeveloperPackedArrayQ[a, type] instead of your functions; see ?DeveloperPackedArrayQ. (At least in V11.2, it has a usage message.) Feb 7 '18 at 15:15
• @MichaelE2 Ah, right, I knew there was a more elegant way... Thanks! Feb 7 '18 at 15:35
• @BrettChampion Thanks for the edit! Feb 7 '18 at 15:36