(* :Title: Difference *) (* :Author: Mark Fisher *) (* :Summary: Code for differencing vectors (and higher order tensors). *) (* :Discussion: Difference is implemented using polynomials in the lag operator to compute the kernel for ListConvolve. *) Difference::usage = "Difference[list] returns the first differnce of the list. Difference[list, d] returns the d-th difference of the list (d >= 0). (For negative d, Difference returns the accumulated sum.) Difference[list, d, s] returns the d-th difference of the list with a span of s (s >= 1). The list can be a matrix or a tensor. Difference[list, polyfun] takes a polynominal function as a second argument to specify the differencing kernel symbolically. In fact, Difference[list, d, s] calls Difference[list, (1-#^s)^d &]. For another example, Difference[list, (1-#^s)^d (1-#)^n &] performs d-th seasonal differencing at span s and n-th differencing at span 1." Difference[list_List, d_Integer:1, s_Integer:1] /; Positive[s] := Switch[{d, s}, {1, 1}, Rest[list] - Drop[list, -1], {0, _}, list, {_?Negative, _}, Nest[Rest @ FoldList[Plus, 0, #] &, list, -d], {_, _}, Difference[list, (1 - #^s)^d &] ] Difference[list_List, poly_, var_] := Difference[list, Function[var, poly]] (* # is used purely as a dummy variable in p[#] *) Difference[list_List, p_Function] /; PolynomialQ[p[#], #] := ListConvolve[DifferenceKernel[p, TensorRank[list]], list] DifferenceKernel[poly_, var_Symbol, rank_Intger:1] := DifferenceKernel[Function[var, poly], rank] DifferenceKernel[p_Function, rank_Integer:1] := With[{ker = CoefficientList[p[#], #]}, If[rank > 1, (Composition @@ Table[List, {rank - 1}]) /@ ker, ker] ]