/* Chebyshev series: a small set of programs to get you started */ ToChebyt(e,x,n):= /* Convert analytic expression, depending on x, to Chebyshev series, via Taylor series */ block([ tay: taylor(e,x,0,n),q,r,ans:[]], power2cheby(makelist(ratcoef(tay,x,i),i,0,n)))$ /* Convert analytic function lambda([x]...expression in x) to Chebyshev series The expression f may be a polynomial or function in other variables, too. The result will be a list of the Chebyshev coefficients. Here we try to make them all floats. We are going to do this by a Discrete Cosine Transform, (DCT) and also by a Fast DCT. */ /* if u is a list of n values of a function f at selected points ... { f(cos( pi*(k+1/2)/n)), k=0.. n-1 } s1: DCT(u) is a list of the Chebyshev series coefficients. */ DCT(u):= /* numeric (slow version) of discrete cosine transform on a list u. */ block([n:length(u), L:[],q,in,nm1], q:?pi/n, in:sqrt(1.0d0/n), nm1:n-1, for i: 0 thru nm1 do L: cons(sum(u[r]*cos(q*(r-1/2)*(nm1-i)),r, 1, n)*in,L), L)$ ( /*this fastDCT works if u is a list of numbers of even length. It uses whatever FFT is in maxima, for good or ill.*/ load(fft)$ /* needs this file loaded */ drv(m):=append(space2(m),space2(reverse(m))), space2(k):= if k=[] then [] else cons(0,cons( first(k),space2(rest(k)))), fastDCT(u):= block([n:length(u),a:fft(drv(u))], 2*sqrt(float(n))* makelist(a[i],i,1,n)), /* gauss-lobatto points*/ glp(n):= makelist(cos(?pi*(i+0.5d0)/n),i,0,n-1)$ glpf(%%f,n):= map(%%f, glp(n)))$ ToCheby2(f,n):= /* n need not be a power of 2, not especially fast */ block([dc:DCT(glpf(f,n)), in:sqrt(1.0d0/n)], apply('chebseries,makelist(dc[i]*2*in*(2- (if(j=n) then 0 else 1)),i,1,n)))$ ToCheby2f(f,n):= /* n MUST be a power of 2, should be faster */ block([dc:fastDCT(glpf(f,n)), in:sqrt(1.0d0/n)], apply('chebseries,makelist(dc[i]*2*in*(2- (if(j=n) then 0 else 1)),i,1,n)))$ /* if you don't like ToCheby2(lambda([x],x^2*sin(x)),8), you can do TC(x^2*sin(x),8, where TC is ...*/ TC(%%f,%%x,n):=ToCheby2s(buildq([f:%%f,x:%%x],lambda([x],f)),n)$ FromCheby(a,x):= /* If x is a symbol, this will convert Chebyshev series to an expression in the power basis, i.e. polynomial in x. If x is a number, this will evaluate the series at that point and provide a number. (if a is just numbers). This algorithm is based on recurrence in Clenshaw alg. */ block([N:length(a)-1,keepfloat:true, bj2:0,bj1:0,bj0:0, z:reverse(a)], for j: 1 thru N do (bj0:2*x*bj1-bj2+first(z), bj2:bj1, bj1:bj0,z:rest(z)), x*bj1+first(z)/2 -bj2)$ /* a test */ small_to_zero(expr,eps):= /* Replaces all numbers smaller in absolute value than EPS by zero . */ fullmap(lambda([x], if numberp(x) and abs(x)