This is probably similar to Salzer's algorithm J.M. refers to, but it seemed easier to figure it out from the recurrence relation
$$T_{n+1} = 2x\,T_{n} - T_{n-1}$$
From it, we get the following identity for multiplying by $x$:
$$\eqalign{
x\, T_0 &= T_1 \cr
x\, T_{n} &= \frac{1}{2}\,T_{n+1} - \frac{1}{2}\,T_{n-1}, \quad n \ge 1\cr
}$$
From the Horner form
$$p(x) = x\, (x\, (x\, (x\, (a_n\, x+a_{n-1})+a_{n-2})+\cdots)+a_1)+a_0$$
we can see that constructing the polynomial can be done by repeated application of the identities above and the relation $a_k = a_k T_0$.
It follows that multiplying by $x$ is a linear operation represented by the matrix
$$
X=\left(
\begin{array}{ccccc}
0 & \frac{1}{2} & & & \\
1 & 0 & \frac{1}{2} & & \\
& \frac{1}{2} & 0& \ddots & \\
& & \ddots & \ddots & \frac{1}{2} \\
& & & \frac{1}{2} & 0 \\
\end{array}
\right)
$$
(* n x n Chebyshev multiplication operator:
chebX[n].cs multiplies length n Chebyshev series cs by x --
the series must end in zero or the degree n-1 term will be lost *)
chebX[n_Integer /; n >= 3] :=
SparseArray[{{2, 1} -> 1, Band[{3, 2}] -> 1/2,
Band[{1, 2}] -> 1/2}, {n, n}];
chebX[2] := SparseArray[{{2, 1} -> 1, Band[{1, 2}] -> 1/2}, {2, 2}];
chebX[1] := SparseArray[{{1, 1} -> 1}, {1, 1}];
J.M.'s example:
poly = 1 - x + 2 x^2 - 5 x^4;
p = Reverse@CoefficientList[poly, x];
n = Length[p];
X = chebX[n];
Fold[X.# + SparseArray[{1 -> #2}, n] &, SparseArray[{}, n], p] // Normal
%.Table[ChebyshevT[n, x], {n, 0, 4}]
% // Expand
(*
{1/8, -1, -(3/2), 0, -(5/8)} -- Coefficients
1/8 - x - 3/2 (-1 + 2 x^2) - 5/8 (1 - 8 x^2 + 8 x^4) -- Chebyshev form
1 - x + 2 x^2 - 5 x^4 -- Expanded power series form
*)
Here's a general function:
Clear[chebForm, chebX, chebFunc];
chebFunc[c_?VectorQ, dom_][x_] := chebFunc[c, dom, x];
chebFunc[c_?VectorQ, {a_, b_}, x_?NumericQ] :=
ChebyshevT[Range[0, Length[c] - 1], (2 x - (a + b))/(b - a)].c;
Normal[chebFunc[c_?VectorQ, {a_, b_}, x_]] ^:=
ChebyshevT[Range[0, Length[c] - 1], (2 x - (a + b))/(b - a)].c;
(* Chebyshev multiplication operator (same as above) *)
chebX[n_Integer /; n >= 3] :=
SparseArray[{{2, 1} -> 1, Band[{3, 2}] -> 1/2,
Band[{1, 2}] -> 1/2}, {n, n}];
chebX[2] := SparseArray[{{2, 1} -> 1, Band[{1, 2}] -> 1/2}, {2, 2}];
chebX[1] := SparseArray[{{1, 1} -> 1}, {1, 1}];
(* convert polynomial to Chebyshev series *)
chebForm[poly_, x_] := chebForm[poly, {x, -1, 1}];
chebForm[poly_, {x_, a_, b_}] := Module[{p, n, X},
p = Reverse@CoefficientList[poly /. x -> (b - a)/2 x + (a + b)/2, x];
n = Length[p];
X = chebX[n];
(* nested multiplication (Horner) *)
chebFunc[Fold[X.# + SparseArray[{1 -> #2}, n] &, SparseArray[{}, n], p], {a, b}]
]
Example: (Normal
converts the chebFunc
to a Chebyshev series in explicit polynomial form.)
cp = chebForm[poly, x];
cp[x]
% // Normal
% // Expand
The Chebyshev series is particularly (numerically) accurate over the interval $[-1,1]$. One can pass a domain $[a,b]$ that is rescaled to $[-1,1]$:
cp = chebForm[poly, {x, -2, 3}];
cp[x]
% // Normal
% // Expand