-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathbary.m
executable file
·130 lines (121 loc) · 3.66 KB
/
bary.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
function fx = bary(x,gvals,xk,ek)
% BARY Barycentric interpolation with arbitrary weights/nodes.
% P = BARY(X,GVALS,XK,EK) interpolates the values GVALS at nodes
% XK in the point X using the barycentric weights EK.
%
% P = BARY(X,GVALS) assumes Chebyshev nodes and weights.
%
% All inputs should be column vectors.
% Copyright 2011 by The University of Oxford and The Chebfun Developers.
% See http://www.maths.ox.ac.uk/chebfun/ for Chebfun information.
warning('off', 'MATLAB:divideByZero'); % TODO: Delete this.
% Parse inputs
n = length(gvals);
bary1flag = 0; % If true, possibly use type-1 barycentric formula
if n == 1, % The function is a constant
fx = gvals*ones(size(x));
return
end
if any(isnan(gvals)), % The function is NaN
fx = NaN(size(x));
return
end
if nargin < 3, % Default to Chebyshev nodes
bary1flag = 1;
xk = chebpts(n);
end
if nargin < 4, % Default to Chebyshev weights
ek = [.5 ; ones(n-1,1)];
ek(2:2:end) = -1;
ek(end) = .5*ek(end);
end
if bary1flag, % Call a barycentric formula of type 1 or 2
ind1 = find(imag(x) | x < -1 | x > 1);
if ~isempty(ind1),
fx = NaN*x;
fx(ind1) = kind1(x(ind1),gvals,xk,ek);
ind2 = find(isnan(fx));
fx(ind2) = kind2(x(ind2),gvals,xk,ek);
else
fx = kind2(x,gvals,xk,ek);
end
else
fx = kind2(x,gvals,xk,ek);
end
% Try to clean up NaNs
for i = find(isnan(fx(:)))',
indx = find(x(i)==xk,1);
if ~isempty(indx),
fx(i) = gvals(indx);
end
end
end
function fx = kind2(x,gvals,xk,ek)
% Evaluate the second-kind barycentric formula. Typically
% this is the standard for evaluating a barycentric interpolant
% on the interval.
if numel(x) < length(xk), % Loop over evaluation points
fx = zeros(size(x)); % Initialise return value
for i = 1:numel(x),
xx = ek ./ (x(i)-xk);
fx(i) = (xx.'*gvals) / sum(xx);
end
else % Loop over barycentric nodes
num = zeros(size(x)); denom = num; % initialise
for i = 1:length(xk),
y = ek(i) ./ (x-xk(i));
num = num + (gvals(i)*y);
denom = denom + y;
end
fx = num ./ denom;
end
end
function fx = kind1(x,gvals,xk,ek)
% Evaluate the first-kind barycentric formula. Typically we
% use this formula for evaluating a polynomial outside the interval.
% If the number of nodes is >=600, we compute the log of the
% nodal polynomial in order to avoid under-/ overflow.
% This method is only called with Chebyshev nodes xk on [-1,1]!
n = length(xk);
scale = 2; x = scale*x; xk = scale*xk;
fx = zeros(size(x)); % Initialise return value
if numel(x) < n, % Loop over evaluation points
for i = 1:numel(x),
fx(i) = (ek./(x(i)-xk)).' * gvals;
end
else % Loop over interpolation nodes
for i = 1:n,
y = ek(i) ./ (x-xk(i));
fx = fx + gvals(i)*y;
end
end
% Evaluate nodal polynomial ell
if n < 600,
ell = ones(size(x));
if numel(x) < n, % Loop over evaluation points
for i = 1:numel(x),
ell(i) = prod(x(i)-xk);
end
else % Loop over interpolation nodes
for i = 1:n,
ell = ell .* (x-xk(i));
end
end
else
ell = zeros(size(x));
if numel(x) < n, % Loop over evaluation points
for i = 1:numel(x),
ell(i) = sum(log(x(i)-xk));
end
else % Loop over interpolation nodes
for i = 1:n,
ell = ell + log(x-xk(i));
end
end
ell = exp(ell);
if isreal(x) && isreal(gvals) && isreal(xk) && isreal(ek),
ell = real(ell);
end
end
fx = fx .* ell * (1/(scale*(1-n))*(-2/scale)^(n-2));
end