For applying some function func
to the coefficients of a polynomial poly
in variables vars
, the best way is, indubitably, Collect[poly, vars, func]
. However, I find that there are also several separate built-in functions in Mathematica:
MonomialList
+Total
,CoefficientRules
+FromCoefficientRules
,CoefficientArrays
+Dot
,CoefficientList
+FromDigits
,GroebnerBasis`DistributedTermsList
+GroebnerBasis`FromDistributedTermsList
, andAlgebra`Polynomial`NestedTermsList
+Algebra`Polynomial`FromNestedTermsList
.
Certain functions are well-known, while others have never been known before. (If Collect
is not allowed, which one would be a better choice?)
Note that each pair can implement such a functionality (i.e., Collect[poly, vars, func]
). I make a list of these implementations as follows:
(*Way 0: using `MonomialList`*)
Plus @@
Replace[
poly ~ MonomialList ~ vars
,
With[{n0 = ToExpression /@ StringTemplate["n``"] /@ Range @ Length
@ vars, avars = Alternatives @@ vars},
c_ * Times @@ (# ^ Optional /@ Thread @ Pattern[n0 // Evaluate,
_]) /; FreeQ[c, avars] ->
func[c] * Inner[Power, #, n0, Times] & /@ Subsets
@ vars ~ PadRight ~ (Automatic ~ Sequence ~ 1)
]
,
{1}
]
(*Way 1: using `CoefficientRules`*)
MapAt[func,
poly ~ CoefficientRules ~ vars, {All, -1}] ~ FromCoefficientRules ~
vars
(*Way 2: using `CoefficientArrays`*)
With[{t = CoefficientArrays[poly, vars]},
WithCleanup[
SetAttributes[func, Listable];
If[First @ t =!= 0,
First @ t // func
,
0
] +
Total[Fold[Dot, #1, vars ~ ConstantArray ~ #2] & ~ MapIndexed
~ (Most[ArrayRules @@ func @ Threaded @ #1] ~
SparseArray ~ ConstantArray[
Length @ vars, #2] & ~ MapIndexed ~
Rest @ t)]
,
ClearAttributes[func, Listable]
]
]
(*Way 3a: using `CoefficientList`*)
Map[
If[# === 0,
#
,
# // func
] &
,
poly ~ CoefficientList ~ vars
,
Length @ vars // List
] ~ Internal`FromCoefficientList ~ vars
(*Way 3b: using `CoefficientList`*)
Fold[
Reverse @ #1 ~ FromDigits ~ #2 &
,
Map[
If[# === 0,
#
,
# // func
] &
,
poly ~ CoefficientList ~ vars
,
Length @ vars // List
]
,
vars
]
(*Way 4: using `GroebnerBasis`DistributedTermsList`*)
MapAt[func,
poly ~ GroebnerBasis`DistributedTermsList ~ vars, {1, ;; ,
2}] // GroebnerBasis`FromDistributedTermsList
(*Way 5a: using `Algebra`Polynomial`NestedTermsList`*)
System`Private`$SystemFileDir <>
System`Dump`fixfile @ "Series`Series`" <>
"x" // DumpGet
System`Private`$SystemFileDir <>
System`Dump`fixfile @ "Algebra`Horner`" <>
"x" // DumpGet
Block[{t =
ExpandAll @ poly ~ Algebra`HornerDump`sparseCoefficientList
~ vars, fa},
fa[x_] := fa[x] =
If[NumericQ @ First @ x,
If[ListQ @ Last @ x,
{Splice @ Most @ x, fa @@ Rest @ x}
,
SubsetMap[func // Map, x, {-1}]
]
,
fa /@ x
];
fa @ t ~ System`SeriesDump`fromSparseCoefficientList ~ vars
]
As you can see, some of them are lengthy and uninteresting, which means that the corresponding functions are not really suited for the above aim. So, what is the exact scope of application of each of functions listed above? And are some of them, apart from being a USP, of no use in practice?