I defined an odd function by
f[0]:=0;
f[x_?Negative]:=-f[-x]
Now I want to define the function for certain known values
Case a) If the known value is positive, it has no problem, i.e.:
f[1]:=7
it perfectly works because when I require f[-1] Mathematica tell me the correct answer -7;
Case b) If the known value is negative
f[-3]:=5
Mathematica store it but when I ask it f[3] it doesn't write -5.
I know this is because of my very definition, but it's an elegant way (possibly without helper functions and without storing manually both values at x and -x) to get the correct result?
Answer
Because Mathematica prioritizes specific function definitions over general ones, simply making the definition
M[i_, j_] := -M[j, i]
will work as long as you only try to evaluate M with values for i and j for which either M[i, j] or M[j, i] have been explicitly defined. Otherwise you get infinite recursion:
M[1, 2] := a
M[4, 3] := b
M[1, 2]
(* a *)
M[2, 1]
(* -a *)
M[3, 4]
(* -b *)
M[1, 3]
(* $RecursionLimit::reclim2: Recursion depth of 1024 exceeded during evaluation of M[3,1]. *)
(* Hold[-M[3, 1]] *)
Clear[M]
To avoid this, we can make a definition for M that only allows itself to be recursed twice, like so:
Module[{n = 0},
M[i_, j_] /; n < 2 := Block[{n = n + 1}, -M[j, i]]
]
The variable n counts the number of times that this definition of M has been called recursively. If n is less than two, the definition applies, and the i and j are swapped. When n is equal to two, the definition doesn't apply, and evaluation terminates. Since at this point the definition has been applied twice, the original expression is returned.
Now we have
M[1, 2] := a
M[4, 3] := b
M[1, 2]
(* a *)
M[2, 1]
(* -a *)
M[3, 4]
(* -b *)
M[1, 3]
(* M[1, 3] *)
(Side note: Mathematica colors the n in the Block expression red, because it thinks that we've created a naming conflict between the Module and the Block, but in fact it works just how we want.)
Comments
Post a Comment