1function L = antiderivmat_1d(s)
2% ANTIDERIVMAT_1D matrix from nodes in 1D to antiderivatives at nodes
3%
4% L = antiderivmat_1d(s) returns (N-1)*N matrix taking values on s,
5% a list of N nodes, to their integrals from the first node to each of the
6% other N-1 nodes in turn. Ie, the antiderivative with constant chosen so that
7% its value at the first node would be zero. Nodes must be spaced in a sensible
8% way. length(s) should not exceed around 30 for stability reasons.
9%
10% Notes: 1) should match Leslie's get_integratemat().
11% 2) Computed in Helsing style, with centering and scaling for stability.
13% Barnett 8/13/24.
15if nargin==0, test_antiderivmat_1d; return; end
17cen = (max(s)+min(s))/2; hwid = (max(s)-min(s))/2; % affine map s to [-1,1]
18s = (s-cen)/hwid;
19n = numel(s); s = s(:); % col vec
20V = ones(n); for j=2:n, V(:,j) = V(:,j-1).*s; end % Vandermonde (polyval) mat
21U = diag(s)*V*diag(1./(1:n)); % mat evaluating an antideriv of poly
22L = (V'\U')'; % backwards-stable way to solve for it (Helsing)
23L = L(2:end,:) - L(1,:); % adjust const to zero at first node
24L = L*hwid; % unscale
26%%%%%%
27function test_antiderivmat_1d
28off = 4.3; sc = 1.7; % test centering and scaling
29x = sc*linspace(-1,1,16)' + off; % nodes
30%x = sc*gauss(16) + off; % nodes
31f = @(x) sin(0.8*x + 0.7); % the antiderivative
32fp = @(x) 0.8*cos(0.8*x + 0.7); % the input func
33Fex = f(x(2:end))-f(x(1)); % exact ans at nodes 2...N, col vec
34L = antiderivmat_1d(x);
35F = L * fp(x); % hit L against vec of func values
36fprintf('max abs err for antideriv on nodes : %.3g\n',max(abs(F - Fex)))
37fprintf('[mat inf-norm = %.3g; max element size = %.3g]\n',norm(L,inf),max(abs(L(:))))