I have programmed and Compile
ed 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.
Answer
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] *)
Comments
Post a Comment