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$ Commented Jan 26, 2017 at 4:19
  • $\begingroup$ Not a complete solution: f[x_?Internal`SyntacticNegativeQ] := -f[-x] $\endgroup$ Commented 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$ Commented 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$ Commented 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$ Commented 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$ Commented Jan 29, 2017 at 19:37
  • $\begingroup$ @Mr.Wizard Sure, I can do that. $\endgroup$ Commented 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$ Commented 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$ Commented 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$ Commented Jan 26, 2017 at 1:53
  • $\begingroup$ @MichaelE2 I got that, thanks. $\endgroup$ Commented Jan 26, 2017 at 1:58

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.