-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathlagrange.m
executable file
·124 lines (109 loc) · 4.13 KB
/
lagrange.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
function result = Lagrange(degree, num_var, num_term, samples, nomials)
result = LagrangeBasis(degree, num_var, num_term, samples, nomials);
if(iscell(result))
lagrangeBasis = result{1};
detVandermonde = result{2};
printf('%d ', detVandermonde);
result = lagrangeBasis;
else
printf('singular');
end
end
function lagrange_basis = LagrangeBasis(degree, num_var, num_term, sample_points, nomial_matrix)
% Input: A polynomial with deg = d, #vars = n, #terms = m = (d+n)!/d!n!, and a vector of m sample points
% Output: A (m+1) x m matrix that gives the Lagrange representation of the polynomial
if(num_var ~= size(sample_points, 2))
error('Each sample needs %d coordinates.', num_var);
end
if(num_term ~= size(sample_points, 1))
sample_points
error('Input polynomial needs %d sample points, but input has only %d samples.', num_term, size(sample_points, 1));
end
% list all nomials of a polynomial with degree <=2
base_matrix = zeros(num_term, num_term);
for i = 1:num_term
for j = 1:num_term
base_matrix(i,j) = poly_eval([1 nomial_matrix(j, :)], sample_points(i, :));
end
end
% Note: we assume the sample points are integers
detVandermonde = round(det(base_matrix));
%printf('det(Vandermonde) = %d\n', d);
if(detVandermonde==0)
lagrange_basis = [];
return
end
coeff_matrix = zeros(num_term, num_term);
for row = 1:num_term
A = base_matrix;
A(row, :) = [];
for col = 1:num_term
B = A;
B(:, col) = []; % B is the co-matrix of A at (row,col)
_sign = 1 - 2*mod(row+col, 2);
coeff_matrix(row, col) = det(B)*(_sign);
end
end
lagrange_basis = {coeff_matrix, detVandermonde};
end
function lagrange_polynomial = LagrangePolynomial(target_polynomial, sample_points, nomial_matrix)
% Input: A polynomial with deg = d, #vars = n, #terms = m = (d+n)!/d!n!, and a vector of m sample points
% Output: A (m+1) x m matrix that gives the Lagrange representation of the target polynomial
degree = max(sum(target_polynomial(:,2:end), 2));
num_var = size(target_polynomial, 2) - 1;
num_term = prod(degree+1:degree+num_var)/factorial(num_var);
if(num_var ~= size(sample_points, 2))
error('Each sample needs %d coordinates.', num_var);
end
if(num_term ~= size(sample_points, 1))
sample_points
error('Input polynomial needs %d sample points, but input has only %d samples.', num_term, size(sample_points, 1));
end
base_matrix = zeros(num_term, num_term);
for i = 1:num_term
for j = 1:num_term
base_matrix(i,j) = poly_eval([1 nomial_matrix(j, :)], sample_points(i, :));
end
end
detVandermonde = det(base_matrix);
if(detVandermonde==0)
lagrange_polynomial = [];
return
end
coeff_matrix = zeros(num_term, num_term);
sample_values = zeros(1, num_term);
for row = 1:num_term
A = base_matrix;
A(row, :) = [];
sample_values(1, row) = poly_eval(target_polynomial, sample_points(row, :));
for col = 1:num_term
B = A;
B(:, col) = []; % B is the co-matrix of A at (row,col)
_sign = 1 - 2*mod(row+col, 2);
coeff_matrix(row, col) = det(B)*(_sign);
end
end
lagrange_polynomial = {(sample_values*coeff_matrix/detVandermonde)' nomial_matrix};
end
function val = poly_eval(polynomial, point)
val = 0;
num_term = size(polynomial, 1);
for k = 1:num_term
val = val + polynomial(k, 1) * prod(point .^ polynomial(k, 2:end));
end
end
if(nargin < 1)
error('Error %d : %s needs a matrix of sample points as input.', nargin, program_name());
end
function serialize(matrix)
w = size(matrix, 1);
h = size(matrix, 2);
for i = 1:w
for j = 1:h
printf('%.5f ', matrix(i,j));
end
end
end
%Lagrange(eval(argv(){1}))
args = argv();
serialize(Lagrange(eval(args{1}), eval(args{2}),eval(args{3}), eval(args{4}), eval(args{5})))