function [result,status] = maple(varargin)
%MAPLE String access to the Maple kernel.
%   MAPLE(STATEMENT) sends STATEMENT to the Maple kernel. 
%   STATEMENT is a string representing a syntactically valid Maple 
%   command. A semicolon for the Maple syntax is appended to STATEMENT
%   if necessary. The result is a string in Maple syntax.
%
%   MAPLE('function',ARG1,ARG2,..,) accepts the quoted name of any Maple
%   function and its corresponding arguments. The Maple statement is formed
%   as: function(arg1, arg2, arg3, ...), that is, commas are added between
%   the arguments. All of the input arguments must be strings that are
%   syntactically valid in Maple. The result is returned as a string in the 
%   Maple syntax.  To convert the result from a Maple string to a symbolic
%   object, use SYM.
%
%   [RESULT,STATUS] = MAPLE(...) returns the warning/error status.
%   When the statement execution is successful, RESULT is the result
%   and STATUS is 0. If the execution fails, RESULT is the corresponding 
%   warning/error message, and STATUS is a positive integer.
%
%   The statements
%      maple traceon  or  maple trace on
%   cause subsequent Maple commands and results to be printed.
%   The statements
%      maple traceoff  or  maple trace off
%   turn off this facility.
%   The statements
%      maple clear  or  maple restart
%   clear off the Maple workspace and reinitialize the Maple kernel.
%
%   MAPLE is not available for general use in the Student Edition.
%
%   See also SYM, SYM/MAPLE

%   Copyright (c) 1993-1999 The Mathworks, Inc. All Rights Reserved.
%   $Revision: 1.28 $  $Date: 1999/01/04 21:55:01 $

% Convert and concatenate arguments.

statement = ' ';
if nargin > 0
   F = varargin{1};
   % Check for 'trace' or 'help'.
   if strncmp(F,'trace',5)
      if nargin == 1 
         v = F(6:end);
      else
         v = varargin{2};
      end
      if strcmp(v,'on') | strcmp(v,'off')
         maplemex(v,3);
         return
      else
         error(['Option ' v ' not recognized.'])
      end
   elseif strncmp(F,'clear',5) | strncmp(F,'restart',7)
      warn=warning;
      warning off;
      lw=lastwarn;
      maplemex('restart;');
      % Reinitialize Maple packages (Linalg, Inttrans, etc.)
      maplemex('with(linalg):');
      maplemex('readlib(ifactor):');
      maplemex('with(inttrans):');
      maplemex('readlib(ztrans):');
      maplemex('readlib(hypergeom):');
      maplemex('readlib(C):');
      maplemex('Digits := 32;');
      lastwarn(lw);
      warning(warn);
      % Establish aliases.
      maplemex('alias(I=I, i=sqrt(-1), j=sqrt(-1), pi=Pi, eye=&*());');
      maplemex('alias(log=ln, inf=infinity, Inf=infinity, fix=trunc);');
      maplemex('alias(asin=arcsin, acos=arccos, atan=arctan);');
      maplemex('alias(asinh=arcsinh, acosh=arccosh, atanh=arctanh);');
      maplemex('alias(acsc=arccsc, asec=arcsec, acot=arccot);');
      maplemex('alias(acsch=arccsch, asech=arcsech, acoth=arccoth);');
      maplemex('alias(besselj=BesselJ, bessely=BesselY);');
      maplemex('alias(besseli=BesselI, besselk=BesselK);');
      maplemex('alias(sinint=Si, cosint=Ci, lambertw=LambertW, zeta=Zeta);');
      maplemex('alias(gamma=GAMMA, eulergamma=gamma, conj=conjugate);');
      return
   elseif strncmp(F,'help',4) & (nargin > 1)
      maplemex(varargin{2},1)
      return
   end
   statement = F;
end
if nargin > 1
   statement(end+1) = '(';
   for k = 2:nargin
      v = varargin{k};
      if ~isstr(v)
         v = char(sym(v));
      end
      statement = [statement v ','];
   end
   statement(end) = ')';
end
if statement(end) ~= ';'
   statement(end+1) = ';';
end

% Convert any floating point syms.

p = findstr(statement,'''');
q = findstr(statement,')');
for k = fliplr(findstr(statement,'''*2^('))
   s = max(p(p<k));
   e = min(q(q>k));
   statement = [statement(1:s-1) fl2str(statement(s:e)) statement(e+1:end)];
end

% Access the Maple kernel via Mex-file interface.

[result,status] = maplemex(statement);

% Handle any error messages.

if (nargout < 2) & (status ~= 0)
   error(result)
end

% Shift decimal point in any Maple E-notation numbers.
result = shiftept(result);

% Put backquotes around all @@ that precede derivative operator D,
% but only if the result contains @@D.
if length(result) > 2
   L = length(findstr(result,'@@D'));
else
   L = [];
end
if length(L)
   result = backat(result);
end

%------------------------------%
function s = fl2str(s)
%FL2STR Convert sym(x,'f') quantity to Maple expression.
%   FL2STR('1.0000000000001'*2^(0)) is 4503599627370497*2^(-52).
 
   p = find(s=='.');
   d = real(s(p+(1:13)))-48;
   k = d > 10;
   d(k) = d(k)-39;
   f = 16^13 + d*16.^(12:-1:0)';
   if s(2) == '-'
      f = -f;
   end
   e = str2double(s(p+19:end-1))-52;
   s = [int2str(f) '*2^(' int2str(e) ')'];


function s = shiftept(s)
%SHIFTEPT Shift decimal point in any Maple E-notation numbers.
%   SHIFTEPT('1234.0E10') is '1.234e13'.

for k = fliplr(findstr('E',s))
   l = length(s);
   if k < 3, break; end
   if s(k-2) ~= '.', break; end
   f = max(find(s(1:k-3) < '0' | s(1:k-3) > '9'));
   if isempty(f), f = 1; else, f = f+1; end
   e = min(find(s(k+2:l) < '0' | s(k+2:l) > '9'));
   if isempty(e), e = l; else, e = e+k; end
   if f < k-3
      s = [s(1:f) '.' s(f+1:k-3) 'e'  ...
          int2str(eval(s(k+1:e))-f+k-3) s(e+1:l)];
   else
      s(k) = 'e';
   end
end


function s = backat(s)
%BACKAT Put backquotes around @@ that precede operator D.
%   BACKAT('xxx@@(Dyyy') is 'xxx`@@`(Dyyy'.

for k = fliplr(findstr('@@(D',s));
   s = [s(1:k-1) '`@@`(D' s(k+4:end)];
end
