# Catching error in middle of evaluation of compiled function

I have programmed and Compileed a complicated numerical function. The function has singularities (i.e. are infinite) at certain input numerical values. I need to catch this problem in the middle of the evaluation and return a more meaningful Message to the user than the default CompiledFunction::cfne.

I can't quite understand the answer to This Question. Would someone help me the following concrete example?

f = Compile[{{x, _Real}, {y, _Real}},
Log[(x - y^2 - 2. x)^2]/(y x^2 - 2 (x + y) - y^2 + 3.)]


For certain values, there are singularities:

f[-196, 14]


CompiledFunction::cfn:
Numerical error encountered at instruction 7; proceeding with uncompiled evaluation

and also

f[1.5, 0]


CompiledFunction::cfne:
Numerical error encountered; proceeding with uncompiled evaluation.

Power::infy: Infinite expression 1/0. encountered.

I would like to trump these default error messages with my own. Is it possible to do this without compromising the speed of the evaluation??

I feel that using a giant If statement such as:

funcForUser::msg = "Singular point.";
funcForUser[x_, y_] := If[x != y^2, f[x, y], Message[funcForUser::msg]; Undefined]


is a very ugly way to solve the problem. And I also don't have the patience to track down all possible conditions that lead to singularities.

## 2 Answers

How about using "RuntimeErrorHandler":

f = Compile[{{x, _Real}, {y, _Real}},
Log[(x - y^2 - 2. x)^2]/(y x^2 - 2 (x + y) - y^2 + 3.),
"RuntimeOptions" -> {"RuntimeErrorHandler" -> Function[Throw[$Failed]]} ]; Catch[Quiet@f[-196, 15]] // AbsoluteTiming (* {0.000019, 0.0000116843} *) Catch[Quiet@f[-196, 14]] // AbsoluteTiming (* {0.000051,$Failed} *)


## Edit

We can even have specific messages too:

(* Copying Ted Ersek's messages *)
f::log="The expression f[1,2] lead to Log[0.0] which evaluates to -\[Infinity].";
f::div="The expression f[1,2] lead to division by zero which evaluates to ComplexInfinity.";

f = Compile[{{x, _Real}, {y, _Real}},
Log[(x - y^2 - 2. x)^2]/(y x^2 - 2 (x + y) - y^2 + 3.),
"RuntimeOptions" -> {"RuntimeErrorHandler" -> Function[{x,y},
Which[x-y^2-2. x==0,
Message[f::log,x,y];
-\[Infinity],
y x^2-2 (x+y)-y^2+3.==0,
Message[f::div,x,y];
ComplexInfinity,
True,
Indeterminate
]
]}
];

f[-196, 14]
CompiledFunction::cfn: Numerical error encountered at instruction 7; proceeding with uncompiled evaluation. >>
f::log: The expression f[-196,14] lead to Log[0.0] which evaluates to -\[Infinity].
(* -\[Infinity] *)

• A bit off-topic - what is the . for in the test: Which[x-y^2-2. x==0, Commented Apr 30, 2015 at 13:40
• @DougKimzey The . is not necessary, I had just copied OP's code. The difference is 2 represents the integer 2 and 2. (or 2.0) represents the float 2.0. It would have been perfectly fine for OP to use 2 there. Commented Apr 30, 2015 at 17:49

I use \$MessagePrePrint = StandardForm since without that the real number 1.5 is displayed in a message as 1.5. However, you might have$MessagePrePrint set to something else. Check is used to control what should happen when a built-in message occurs. Quiet prevents the built-in message from being displayed. I made a pure function (i.e. #1,#2,& notation) to make it a bit faster.

\$MessagePrePrint=StandardForm;
f::log="The expression f[1,2] lead to Log[0.0] which evaluates to
Indeterminate.";
f::div="The expression f[1,2] lead to division by zero which evaluates to
ComplexInfinity.";
With[{fc=Compile[{{x,_Real},{y,_Real}},Log[(x-y^2-2. x)^2]/(y x^2-2 (x+y)-y^2+3.)]},
f=Quiet[Check[Check[fc[#1,#2],
Message[f::log,#1,#2];Indeterminate,{CompiledFunction::cfn}],
Message[f::div,#1,#2]ComplexInfinity,{CompiledFunction::cfne,Power::infy}],
{CompiledFunction::cfn,CompiledFunction::cfne,Power::infy}]&];


Now we have

f[-196,14]
f:log : The expression f[-196,14] lead to Log[0.0] which evaluates to Indeterminate.
(*Indeterminate*)


and

f[1.5,0]
f:div : The expression f[1.5,0] lead to division by zero which evaluates to ComplexInfinity.
(*ComplexInfinity*)
`