function [p, err] = polyfitn(varargin) % polyfitn(f, order) -- ND polynomial fit. % polyfitn('demo') demonstrates itself. % polyfitn(N, order) demonstrates itself with N random % points f(x, y) = (x - y).^order. Defaults: % N = 10, order = 1. % polyfitn(f, order) fits the data, a matrix arranged % column-wise as [x y z ... f(x, y, z, ...)], to % the given maximum order (default = 1). The % result is an ND array. Each array index, minus % one (1), represents the powers of the independent % variables. For example, the index [1 2 3] would % denote the x^0 + y^1 + z^2 term. Use "polyvaln" % to evaluate the polynomial. % polyfitn(x, y, ..., f, order) is an alternative % syntax. % [p, err] = ... also returns the error-norm % of the fit. % % Also see: polyvaln. % Copyright (C) 2003 Dr. Charles R. Denham, ZYDECO. % All Rights Reserved. % Disclosure without explicit written consent from the % copyright owner does not constitute publication. % Version of 22-Apr-2003 10:47:46. % Updated 29-Apr-2003 13:15:41. % Strange behavior: polyfit(100, 9) does not work, % whereas (99, 9) and (101, 9) do work. if nargin < 1 help(mfilename) varargin = {'demo'}; end if nargin < 2 & isequal(varargin{1}, 'demo') varargin{1} = 20; end if ischar(varargin{1}) varargin{1} = eval(varargin{1}); end if nargin < 3 & length(varargin{1}) == 1 N = varargin{1}; x = rand(N, 1); y = rand(size(x)); order = 1; if length(varargin) > 1 order = varargin{2}; end if ischar(order), order = eval(order); end f = (x - y).^order; [pp, err] = feval(mfilename, x, y, f, order); if nargout > 0, p = pp; end xi = linspace(0, 1, 11); yi = xi; [xi, yi] = meshgrid(xi, yi); g = zeros(size(xi)); g(:) = polyvaln(pp, xi(:), yi(:)); hold off surf(xi, yi, g, ... 'FaceColor', 'y', 'EraseMode', 'xor') hold on plot3(x, y, f, 'k*', 'EraseMode', 'xor') hold off xlabel X ylabel Y zlabel Z title(['Error Norm: ' num2str(err)]) figure(gcf) set(gcf, 'Name', ... [mfilename ' ' int2str(N) ' ' int2str(order)]) return end if length(varargin) > 2 if length(varargin{end}) == 1 order = varargin{end}; data = [varargin{1:end-1}]; else order = 1; data = [varargin{:}]; end if nargout > 1 [p, err] = feval(mfilename, data, order); else p = feval(mfilename, data, order); end return end data = varargin{1}; if nargin > 1 order = varargin{2}; else order = 0; end [m, n] = size(data); sz = [order+1 order+1]; % Exponents for Vandermonde matrix. sub = cell(1, n-1); [sub{:}] = ind2sub(sz, 1:prod(sz)); for i = 1:length(sub) sub{i} = sub{i}(:); end expon = [sub{:}] - 1; % Trim exponents to requested order. for k = 1:length(expon) if sum(expon(k, :)) > order expon(k, :) = NaN; end end % Vandermonde matrix. vander = zeros(m, prod(sz)); k = 0; for i = 1:prod(sz) x = data(:, 1:n-1); k = k+1; ex = expon(k, :); if all(isfinite(ex)) ex = repmat(ex, [m 1]); x = data(:, 1:n-1) .^ ex; vander(:, k) = prod(x, 2); end end % Solve. p = zeros([order+1 order+1]); warning off % Vander is habitually rank-deficient. p(:) = vander \ data(:, end); warning on if order == 0, p = p(1); end % Error-norm. if nargout > 1 err = norm(polyvaln(p, data(:, 1:end-1)) - data(:, end)); end