3
$\begingroup$

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?

$\endgroup$
4
  • $\begingroup$ You asked an almost identical question: mathematica.stackexchange.com/questions/136201/…. The solution I provided there will work here too. $\endgroup$
    – yohbs
    Jan 26, 2017 at 4:19
  • $\begingroup$ Not a complete solution: f[x_?Internal`SyntacticNegativeQ] := -f[-x] $\endgroup$ Jan 26, 2017 at 5:30
  • $\begingroup$ The answer provided in this question is superior to the answer contained in the other question, and it generalises better this way. As such I vote to leave this question open, if this remains open I'd argue the other question should be closed as duplicate of this one. $\endgroup$
    – Feyre
    Jan 26, 2017 at 8:45
  • $\begingroup$ Note to community: I intend to Merge this question with the presently marked duplicate which will move its answers to that question. This action is not revertible. If anyone objects to this plan please voice your concern ASAP. Thanks. $\endgroup$
    – Mr.Wizard
    Jan 30, 2017 at 8:36

2 Answers 2

12
$\begingroup$

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.)

$\endgroup$
5
  • $\begingroup$ Edited to simplify the definition of f[x]. $\endgroup$ Jan 27, 2017 at 3:57
  • $\begingroup$ are you willing to rewrite your answer to match the example given in mathematica.stackexchange.com/questions/136201/…? If so I think we could close this question and then merge it into the other, thereby moving your answer. $\endgroup$
    – Mr.Wizard
    Jan 29, 2017 at 19:37
  • $\begingroup$ @Mr.Wizard Sure, I can do that. $\endgroup$ Jan 30, 2017 at 1:40
  • $\begingroup$ @Mr.Wizard I edited the answer to refer to the other question. If you end up not merging, please revert it. $\endgroup$ Jan 30, 2017 at 3:06
  • $\begingroup$ Thanks Simon. I intend to do that shortly but since a Merge is not reversible I'll leave at least a small window for objections. $\endgroup$
    – Mr.Wizard
    Jan 30, 2017 at 8:37
2
$\begingroup$

Your definition only inverts negative argument to positive but not the other way. And when you define f[-3]=5 and run f[3], 3 is not negative, so it will not be evaluated.

One way to solve this problem is to simply remove that pattern test, i.e. ?Negative

Following Michael's suggestion, if you don't remove that test, adding a definition for ?Positive also works, in case the argument becomes something strange.

$\endgroup$
2
  • $\begingroup$ You might want to test that.... $\endgroup$
    – Michael E2
    Jan 26, 2017 at 1:53
  • $\begingroup$ @MichaelE2 I got that, thanks. $\endgroup$
    – vapor
    Jan 26, 2017 at 1:58

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