comparison scripts/specfun/legendre.m @ 12893:72ffa81a68d4 stable

legendre.m: Allow ND-array inputs (Bug #33526). * legendre.m: Allow ND-array inputs (Bug #33526).
author Marco Caliari <marco.caliari@univr.it>
date Wed, 27 Jul 2011 11:21:21 -0700
parents c792872f8942
children 72c96de7a403
comparison
equal deleted inserted replaced
12892:67bf9b30f3f9 12893:72ffa81a68d4
164 164
165 if (!isscalar (n) || n < 0 || n != fix (n)) 165 if (!isscalar (n) || n < 0 || n != fix (n))
166 error ("legendre: N must be a non-negative scalar integer"); 166 error ("legendre: N must be a non-negative scalar integer");
167 endif 167 endif
168 168
169 if (!isvector (x) || !isreal (x) || any (x < -1 | x > 1)) 169 if (!isreal (x) || any (x(:) < -1 | x(:) > 1))
170 error ("legendre: X must be real-valued vector in the range -1 <= X <= 1"); 170 error ("legendre: X must be real-valued vector in the range -1 <= X <= 1");
171 endif 171 endif
172 172
173 if (nargin == 3) 173 if (nargin == 3)
174 normalization = lower (normalization); 174 normalization = lower (normalization);
185 scale = 1; 185 scale = 1;
186 otherwise 186 otherwise
187 error ('legendre: expecting NORMALIZATION option to be "norm", "sch", or "unnorm"'); 187 error ('legendre: expecting NORMALIZATION option to be "norm", "sch", or "unnorm"');
188 endswitch 188 endswitch
189 189
190 if (rows (x) != 1) 190 scale = scale * ones (size (x));
191 x = x';
192 endif
193 scale = scale * ones (1, numel (x));
194 191
195 ## Based on the recurrence relation below 192 ## Based on the recurrence relation below
196 ## m m m 193 ## m m m
197 ## (n-m+1) * P (x) = (2*n+1)*x*P (x) - (n+1)*P (x) 194 ## (n-m+1) * P (x) = (2*n+1)*x*P (x) - (n+1)*P (x)
198 ## n+1 n n-1 195 ## n+1 n n-1
199 ## http://en.wikipedia.org/wiki/Associated_Legendre_function 196 ## http://en.wikipedia.org/wiki/Associated_Legendre_function
200 197
201 overflow = false; 198 overflow = false;
199 retval = zeros([n+1, size(x)]);
202 for m = 1:n 200 for m = 1:n
203 lpm1 = scale; 201 lpm1 = scale;
204 lpm2 = (2*m-1) .* x .* scale; 202 lpm2 = (2*m-1) .* x .* scale;
205 lpm3 = lpm2; 203 lpm3 = lpm2;
206 for k = m+1:n 204 for k = m+1:n
215 || any (abs (lpm3) > realmax)) 213 || any (abs (lpm3) > realmax))
216 overflow = true; 214 overflow = true;
217 endif 215 endif
218 endif 216 endif
219 endfor 217 endfor
220 retval(m,:) = lpm3; 218 retval(m,:) = lpm3(:);
221 if (strcmp (normalization, "unnorm")) 219 if (strcmp (normalization, "unnorm"))
222 scale = -scale * (2*m-1); 220 scale = -scale * (2*m-1);
223 else 221 else
224 ## normalization == "sch" or normalization == "norm" 222 ## normalization == "sch" or normalization == "norm"
225 scale = scale / sqrt ((n-m+1)*(n+m))*(2*m-1); 223 scale = scale / sqrt ((n-m+1)*(n+m))*(2*m-1);
226 endif 224 endif
227 scale = scale .* sqrt(1-x.^2); 225 scale = scale .* sqrt(1-x.^2);
228 endfor 226 endfor
229 227
230 retval(n+1,:) = scale; 228 retval(n+1,:) = scale(:);
229
230 if (isvector (x))
231 ## vector case is special
232 retval = reshape (retval, n + 1, length (x));
233 endif
231 234
232 if (strcmp (normalization, "sch")) 235 if (strcmp (normalization, "sch"))
233 retval(1,:) = retval(1,:) / sqrt (2); 236 retval(1,:) = retval(1,:) / sqrt (2);
234 endif 237 endif
235 238
237 warning ("legendre: overflow - results may be unstable for high orders"); 240 warning ("legendre: overflow - results may be unstable for high orders");
238 warned_overflow = true; 241 warned_overflow = true;
239 endif 242 endif
240 243
241 endfunction 244 endfunction
245
242 246
243 %!test 247 %!test
244 %! result = legendre (3, [-1.0 -0.9 -0.8]); 248 %! result = legendre (3, [-1.0 -0.9 -0.8]);
245 %! expected = [ 249 %! expected = [
246 %! -1.00000 -0.47250 -0.08000 250 %! -1.00000 -0.47250 -0.08000
276 %! assert (result(end) < -1.7976e308 && all (isfinite (result(1:end-1)))); 280 %! assert (result(end) < -1.7976e308 && all (isfinite (result(1:end-1))));
277 281
278 %!test 282 %!test
279 %! result = legendre (150, 0); 283 %! result = legendre (150, 0);
280 %! ## This agrees with Matlab's result. 284 %! ## This agrees with Matlab's result.
281 %! assert (result(end), 3.7532741115719e+306, 0.0000000000001e+306) 285 %! assert (result(end), 3.7532741115719e+306, 0.0000000000001e+306);
282 286
283 %!test 287 %!test
284 %! result = legendre (0, 0:0.1:1); 288 %! result = legendre (0, 0:0.1:1);
285 %! assert (result, full(ones(1,11))) 289 %! assert (result, full(ones(1,11)));
290
291 %!test
292 %! result = legendre (3, [-1,0,1;1,0,-1]);
293 %! ## Test matrix input
294 %! expected(:,:,1) = [-1,1;0,0;0,0;0,0];
295 %! expected(:,:,2) = [0,0;1.5,1.5;0,0;-15,-15];
296 %! expected(:,:,3) = [1,-1;0,0;0,0;0,0];
297 %! assert (result, expected);
298
299 %!test
300 %! result = legendre (3, [-1,0,1;1,0,-1]');
301 %! expected(:,:,1) = [-1,0,1;0,1.5,0;0,0,0;0,-15,0];
302 %! expected(:,:,2) = [1,0,-1;0,1.5,0;0,0,0;0,-15,0];
303 %! assert (result, expected);
286 304
287 %% Check correct invocation 305 %% Check correct invocation
288 %!error legendre (); 306 %!error legendre ();
289 %!error legendre (1); 307 %!error legendre (1);
290 %!error legendre (1,2,3,4); 308 %!error legendre (1,2,3,4);