1%% Copyright (C) 2014-2016 Colin B. Macdonald 2%% 3%% This file is part of OctSymPy. 4%% 5%% OctSymPy is free software; you can redistribute it and/or modify 6%% it under the terms of the GNU General Public License as published 7%% by the Free Software Foundation; either version 3 of the License, 8%% or (at your option) any later version. 9%% 10%% This software is distributed in the hope that it will be useful, 11%% but WITHOUT ANY WARRANTY; without even the implied warranty 12%% of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 13%% the GNU General Public License for more details. 14%% 15%% You should have received a copy of the GNU General Public 16%% License along with this software; see the file COPYING. 17%% If not, see <http://www.gnu.org/licenses/>. 18 19%% -*- texinfo -*- 20%% @documentencoding UTF-8 21%% @defmethod @@sym limit (@var{expr}, @var{x}, @var{a}, @var{dir}) 22%% @defmethodx @@sym limit (@var{expr}, @var{x}, @var{a}) 23%% @defmethodx @@sym limit (@var{expr}, @var{a}) 24%% @defmethodx @@sym limit (@var{expr}) 25%% Evaluate symbolic limits. 26%% 27%% The limit of @var{expr} as @var{x} tends to @var{a} from 28%% @var{dir}. @var{dir} can be @code{left} or @code{right}. 29%% 30%% Examples: 31%% @example 32%% @group 33%% syms x 34%% L = limit(sin(x)/x, x, 0) 35%% @result{} L = (sym) 1 36%% L = limit(1/x, x, sym(inf)) 37%% @result{} L = (sym) 0 38%% L = limit(1/x, x, 0, 'left') 39%% @result{} L = (sym) -∞ 40%% L = limit(1/x, x, 0, 'right') 41%% @result{} L = (sym) ∞ 42%% @end group 43%% @end example 44%% 45%% If @var{x} is omitted, @code{symvar} is used to determine the 46%% variable. If @var{a} is omitted, it defaults to 0. 47%% 48%% @var{dir} defaults to @code{right}. Note this is different from 49%% Matlab's Symbolic Math Toolbox which returns @code{NaN} for 50%% @code{limit(1/x, x, 0)} 51%% (and @code{+/-inf} if you specify @code{left/right}). I'm not 52%% sure how to get this nicer behaviour from SymPy. 53%% FIXME: this is https://github.com/cbm755/octsympy/issues/74 54%% 55%% @seealso{@@sym/diff} 56%% @end defmethod 57 58 59function L = limit(f, x, a, dir) 60 61 if (nargin > 4 || nargin < 1) 62 print_usage (); 63 end 64 65 f = sym(f); 66 if (nargin < 4) 67 dir= 'right'; 68 end 69 if (nargin == 2) 70 a = x; 71 x = symvar(f, 1); 72 end 73 if (nargin == 1) 74 x = symvar(f, 1); 75 a = 0; 76 end 77 78 switch (lower (dir)) 79 case {'left' '-'} 80 pdir = '-'; 81 case {'right' '+'} 82 pdir = '+'; 83 otherwise 84 print_usage (); 85 end 86 87 if (isempty (x)) 88 L = f; 89 return 90 end 91 92 L = elementwise_op ('lambda f, x, a, dir: f.limit(x, a, dir=dir)', ... 93 sym(f), sym(x), sym(a), pdir); 94end 95 96 97%!error <Invalid> limit (sym(1), 2, 3, 4, 5) 98 99%!shared x, oo 100%! syms x 101%! oo = sym(inf); 102 103%!assert (isa (limit(x, x, pi), 'sym')) 104 105%!assert (isequal (limit(x, x, pi), sym(pi))) 106 107%!assert (isequal (limit(sin(x)/x, x, 0), 1)) 108 109%!test 110%! % left/right-hand limit 111%! assert (isequal (limit(1/x, x, 0, 'right'), oo)) 112%! assert (isequal (limit(1/x, x, 0), oo)) 113%! assert (isequal (limit(1/x, x, 0, 'left'), -oo)) 114%! assert (isequal (limit(1/x, x, oo), 0)) 115%! assert (isequal (limit(sign(x), x, 0, 'left'), -1)) 116%! assert (isequal (limit(sign(x), x, 0, 'right'), 1)) 117%! assert (isequal (limit(sign(x), x, 0, '-'), -1)) 118%! assert (isequal (limit(sign(x), x, 0, '+'), 1)) 119 120%!test 121%! % matrix 122%! syms y 123%! A = [x 1/x x*y]; 124%! B = sym([3 sym(1)/3 3*y]); 125%! assert (isequal (limit(A, x, 3), B)) 126 127%!test 128%! % omitting arguments 129%! syms a 130%! assert (isequal (limit(a), 0)) 131%! assert (isequal (limit(a*x+a+2), a+2)) 132%! assert (isequal (limit(a*x+a+2, 6), 7*a+2)) 133 134%!test 135%! % constants 136%! assert (isequal (limit(sym(6)), 6)) 137%! assert (isequal (limit(sym(6), 7), 6)) 138%! assert (isequal (limit([sym(6) sym(2)], 7), [6 2])) 139 140%!test 141%! % double constant, with sym limit 142%! a = limit (6, sym(0)); 143%! assert (isa (a, 'sym')) 144%! assert (isequal (a, sym(6))) 145