7

I have a function that I am defining as (assume m,n,a,b are non-negative integers):

myfcn[x_^m_ p_^n_, x_^a_ p_^b_] := basefcn[m, n, a, b];

and then extending to all polynomials by linearity.

The way I defined the function above works as long as m,n,a,b are all greater than 1, but fails otherwise. For instance, I want myfcn[x p^2, p] to evaluate to basefcn[1,2,0,1], but mathematica does not recognize that this is what I want.

How do I extend my function definition to include these cases without explicitly writing out all possible input forms?

Thanks.

seismatica
  • 5,101
  • 1
  • 22
  • 33

2 Answers2

5

Some silliness with Optional i.e. : (thanks @Mr.Wizard for the -. tip). I thought I could ride the Optional gravy train all the way but just could not find a way to deal with arguments that equal to 1 i.e. x^0 p^0, so I defined another instance of the function to convert 1 to x^0 p^0 (and then pass it back to the original definition) (oh yes I can!). This also does seem to be monomial-only.

A small note: since x and p have to be specified (otherwise x could just as well stand for p_), I left the base as x and p, instead of x_ and p_; they are not used by the function anyway so it really doesn't matter much.

ClearAll[myfcn, x, p]
SetAttributes[myfcn, HoldAll]

myfcn[(c1 : 1 : 1) (x1 : x^m_. : x^0) (p1 : p^n_. : p^0),
  (c2 : 1 : 1) (x2 : x^a_. : x^0) (p2 : p^b_. : p^0)] :=
 basefcn[m, n, a, b]

myfcn[x p^2, p]
(* basefcn[1, 2, 0, 1] *)

myfcn[x p^2 + p, p]
(* myfcn[x p^2 + p, p] *)

{Defer[myfcn][Sequence @@ #], myfcn @@ #} & /@ 
  Partition[Flatten[Outer[x^#1 p^#2 &, {0, 1, 2}, {0, 1, 2}]]~Prepend~1, 2] // 
 Grid[#, Frame -> All] &

Mathematica graphics

seismatica
  • 5,101
  • 1
  • 22
  • 33
  • 1
    I was about to post an answer using Optional. You win this time. However, you do not need to use e.g. (m_: 1) as m_. will do since 1 is the default value for Power. This significantly streamlines your code. See: (51585) – Mr.Wizard Aug 20 '14 at 03:54
  • Also I note that you are using literal x and p in your function whereas by my interpretation of the question these are arbitrary symbols or expressions. – Mr.Wizard Aug 20 '14 at 03:56
  • @Mr.Wizard Thanks so much for the _. tip! Could I edit my post to add that in? Also, the reason I chose to use explicit x and p is because the function the OP defines (with x_ and p_) is ambiguous. For example, using OP's definition, myfunc[x^2, p^3] could be matched such that x^2 matches x_^m_, and p^3 matches p_^b_. However, x^2 could just as well match with p_^n_, and p^3 with x_^a_, since x_ and p_ in OP's definition could be anything. Please let me know if I might be confused on that point. – seismatica Aug 20 '14 at 04:12
  • I also apologize if my answer had made you abandon your answer. I don't doubt your method with Optional would be better/more elegant than mine. – seismatica Aug 20 '14 at 04:17
  • Your method looks fine. I was taking a different approach but I don't think it would be useful to the OP as there were unresolved issues, which your choice of literal x and p better addressed. – Mr.Wizard Aug 20 '14 at 05:01
3

Perhaps

myfcn2[arg1_, arg2_] := basefcn @@ Flatten[Exponent[#, {x, p}, List] & /@ {arg1, arg2}]; 
myfcn2[x p^2, p]
(* basefcn[1, 2, 0, 1] *)

Update: To restrict the arguments to monomials (Thanks: @wxffles )

ClearAll[myfnc3];
myfcn3[arg1_, arg2_] /; FreeQ[{arg1, arg2}, Plus] := 
      basefcn @@ Flatten[Exponent[#, {x, p}, List] & /@ {arg1, arg2}];
myfcn3[x p^2 , p]
(* basefcn[1, 2, 0, 1] *)
myfcn3[x p^2 + p , p]
(* myfcn3[p + p^2 x, p] *)
kglr
  • 394,356
  • 18
  • 477
  • 896
  • Is there a way I can make it only use the implementation you give when arg1 and arg2 are monomials? Because if they are polynomials (i.e. arg1 = x p + x^2 p), then this implementation does not work properly. After I define it successfully on monomials, I will extend to all polynomials by linearity. –  Aug 20 '14 at 02:51
  • Your could use arg1_ /; FreeQ[arg1, Plus] to ensure monomialism. – wxffles Aug 20 '14 at 03:07
  • Thank you @wxffles! -- this is much neater than the monster I was about to suggest: myfcnX[arg1_, arg2_] /; (And @@ (Length[MonomialList[#]] == 1 & /@ {arg1, arg2})) := ... :) – kglr Aug 20 '14 at 03:18
  • This code gives the same results for myfcn3[2 x, p] and myfcn3[x,p]. This gives problems when I try to extend it to arbitrary polynomials. –  Aug 20 '14 at 06:10
  • @user2397833, yes it does. I presume you need myfcn3[2 x, p] to return unevaluated? – kglr Aug 20 '14 at 06:16
  • yes, that is correct. –  Aug 20 '14 at 07:23