6
$\begingroup$

I'm trying to define a function myFunc with a special case:

myFunc[x_, y_] = (x^2 - y) Log[x^2 - y];
myFunc[x_, x_^2] = 0;

This seems to work in limited cases only:

In[1] := myFunc[x, x^2]
Out[1] = 0

But if I put in numbers, or anything else, it fails. How would I fix this?

In[2] := myFunc[2.1, 2.1^2]
Out[2] = Indeterminate

In[3] := myFunc[a^2, a^4]
Out[3] = Indeterminate

I am more interested in making case with numbers to work. What should I do?

$\endgroup$
1
  • $\begingroup$ Patterns are not a good way to define functions with special cases, see my comment and answer below. $\endgroup$
    – Jens
    Jan 3, 2013 at 4:33

3 Answers 3

9
$\begingroup$

You could try:

myFunc[x_, y_] := (x^2 - y) Log[x^2 - y];
myFunc[x_, y_] := 0 /; y == x^2;

{myFunc[2.1, 2.1^2], myFunc[a^2, a^4]}
(*
-> {0,0}
*)
$\endgroup$
3
  • $\begingroup$ +1 This definitely achieves what was asked (even though the example function doesn't really need a case distinction). $\endgroup$
    – Jens
    Jan 3, 2013 at 4:45
  • $\begingroup$ Perfect! Upon further usage, I discovered that I should define the special cases before the general function for this to work fool-proof. Can you verify/comment on this? $\endgroup$
    – QuantumDot
    Jan 3, 2013 at 6:18
  • $\begingroup$ @QuantumDot Sorry, but I'm not sure about how Mathematica does the prioritization of pattern testing. Perhaps that is a good question ... if it wasn't asked before :) $\endgroup$ Jan 3, 2013 at 7:06
9
$\begingroup$

Your problem is not that the function needs to have a special value at a certain point, because the function is in fact continuous at the point you're trying to single out. The only problem is that Mathematica isn't calculating the limit $\lim_{\epsilon\to 0}\epsilon\ln(\epsilon) = 0$ when it should.

Instead of singling out the offending point by pattern matching, I would take the more mathematically motivated route of specifying that a limit exists and should be taken:

Clear[myFunc]
myFunc[x_, y_] := Limit[d Log[d], d -> x^2 - y];
myFunc[4, 4]
(* ==> 12 Log[12] *)
myFunc[4, 16]
(* ==> 0 *)

Now you don't need any case distinctions at all.

Edit

Looking at the other solutions, one thing came to mind that was missing if you do want to make a case distinction (i.e., if you had a different function in your example that requires it):

Clearly you want

myFunc[a^2, a^4] == 0

But what about this?

myFunc[a^2, b^4] /. b -> a

Strictly speaking, all definitions including mine from above make a potential mistake here in assuming that a and b are different when returning a result from myFunc, so that if you subsequently set b -> a you get an error from the $0 \times \ln 0$ expression.

To circumvent that, it might be best to insist on keeping the result of myFunc conditional if it gets symbolic parameters. Then you could instead define it like this:

Clear[myFunc];
myFunc[x_, y_] := 
  Piecewise[{{(x^2 - y) Log[x^2 - y], x^2 != y}, {0, True}}];
myFunc[2, 4]
(* ==> 0 *)
myFunc[a^2, a^4]
(* ==> 0 *)
myFunc[a^2, b^4]

$\begin{cases} \left(a^4-b^4\right) \log \left(a^4-b^4\right) & a^4\neq b^4 \\ 0 & \text{True} \end{cases}$

Now the result of the last symbolic input is the unevaluated Piecewise expression, and consequently we can move on without fear, getting the correct result if we later look at the problematic special case:

myFunc[a^2, b^4] /. b -> a
(* ==> 0 *)

Again, in your specific case that's not the best approach because you can use a limiting process to define the function.

$\endgroup$
2
  • $\begingroup$ Your second solution involving Piecewise is particularly useful to me since the problem I have at hand is a function involving 3 argument with lots of different Log's which have many limiting cases. $\endgroup$
    – QuantumDot
    Jan 3, 2013 at 6:29
  • $\begingroup$ @QuantumDot If the answer is useful to you ... vote it up :) $\endgroup$ Jan 3, 2013 at 7:07
1
$\begingroup$

You can set the function to Hold:

SetAttributes[myFunc, HoldAll];
myFunc[x_, y_] = (x^2 - y) Log[x^2 - y];
myFunc[x_, x_^2] = 0;

myFunc[2.1, 2.1^2]
0

But this is not a "robust" approach without further fiddling. For example:

myFunc[5, (2+3)^2]
Indeterminate
$\endgroup$
2
  • $\begingroup$ This may not be mathematically robust but it is the desired pattern and the way I would approach this myself. +1 $\endgroup$
    – Mr.Wizard
    Jan 3, 2013 at 0:48
  • $\begingroup$ This will fail for example for myFunc[Sin[Pi/4], 1/2] $\endgroup$
    – Jens
    Jan 3, 2013 at 4:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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