What Has Changed in Maple V Release 5

 Maple V Release 5 includes significant enhancements to some existing features.  A brief description of the most interesting enhancements follows.

Lexical Scoping

 Introduction
 Maple allows you to create nested procedure definitions.  This means that procedures can be defined within other procedures, or return procedures as expected output.  Lexical scoping allows a nested procedure to access the variables which are located in surrounding procedures. You can now program in Maple and achieve better encapsulation.
 In previous versions of Maple, it was difficult to have a nested procedure access the variables of an enclosing procedure.  Procedures could only share variables if the variables were global.
 An Example
 The simple example in this section uses the concept of lexical scoping of parameters to define a procedure that creates new procedures that depend upon the input to the top-level procedure.
 > makeincr := proc(n::integer) # outer procedure         local   incr;         incr := proc(i::integer) # inner procedure                 RETURN( i + n ); # n is the parameter to makeincr         end;         RETURN( incr ); end;
 ${\mathrm{makeincr}}{:=}{\mathbf{proc}}\left({n}{::}{\mathrm{integer}}\right)\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{local}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathrm{incr}}{;}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathrm{incr}}{:=}{\mathbf{proc}}\left({i}{::}{\mathrm{integer}}\right)\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathrm{RETURN}}{}\left({i}{+}{n}\right)\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{end proc}}{;}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathrm{RETURN}}{}\left({\mathrm{incr}}\right)\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{end proc}}$ (1)
 > add2 := makeincr( 2 );
 ${\mathrm{add2}}{≔}{\mathrm{incr}}$ (2)
 ${2}$ (3)
 ${7}$ (4)
 > addminus1 := makeincr( -1 );
 ${\mathrm{addminus1}}{≔}{\mathrm{incr}}$ (5)
 ${-1}$ (6)
 ${4}$ (7)
 • In the preceding example, a procedure incr is nested in an outer procedure makeincr.  The outer procedure returns as its value the nested procedure incr. The parameter n of makeincr is lexically scoped: its value is visible within the inner procedure incr, where it is used to determine by how much to increment its own parameter i. The value of  n is passed to makeincr as part of the definition of the inner procedure incr.
 • Notice that if one sets the kernel options variable warnlevel to 4, a warning is issued about the presence of a lexically scoped parameter.  The warning identifies the new feature in Release 5, whereas in previous versions of Maple, the variable n occurring in the definition of the inner procedure incr would be regarded as a global variable.

Differential Equations and the DEtools package

 The DEtools package is not new in Release 5, but it has been significantly expanded, with dramatic improvements both in performance and power. DEtools incorporated packages that were previously share packages: ODEtools (here DEtools,Lie) for computing using Lie symmetry methods and classifying ODEs; diffop , for computing with linear differential operators; and Poincare for plotting 2D/3D projections of Poincare sections of Hamiltonian systems.
 The dsolve command has also been rewritten to take direct advantage of the new implementation of symmetry methods now available in DEtools, resulting in a remarkable improvement in its solving performance.
 Finally, the odeadvisor command, originally from ODEtools, can be used to classify ODEs in general, and contains more help pages with related information and solving tips.
 Many more examples can be found in the example worksheets examples/diffop and examples/linearode.
 > with( DEtools );
 $\left[{\mathrm{AreSimilar}}{,}{\mathrm{Closure}}{,}{\mathrm{DEnormal}}{,}{\mathrm{DEplot}}{,}{\mathrm{DEplot3d}}{,}{\mathrm{DEplot_polygon}}{,}{\mathrm{DFactor}}{,}{\mathrm{DFactorLCLM}}{,}{\mathrm{DFactorsols}}{,}{\mathrm{Dchangevar}}{,}{\mathrm{Desingularize}}{,}{\mathrm{FindODE}}{,}{\mathrm{FunctionDecomposition}}{,}{\mathrm{GCRD}}{,}{\mathrm{Gosper}}{,}{\mathrm{Heunsols}}{,}{\mathrm{Homomorphisms}}{,}{\mathrm{IVPsol}}{,}{\mathrm{IsHyperexponential}}{,}{\mathrm{LCLM}}{,}{\mathrm{MeijerGsols}}{,}{\mathrm{MultiplicativeDecomposition}}{,}{\mathrm{ODEInvariants}}{,}{\mathrm{PDEchangecoords}}{,}{\mathrm{PolynomialNormalForm}}{,}{\mathrm{RationalCanonicalForm}}{,}{\mathrm{ReduceHyperexp}}{,}{\mathrm{RiemannPsols}}{,}{\mathrm{Xchange}}{,}{\mathrm{Xcommutator}}{,}{\mathrm{Xgauge}}{,}{\mathrm{Zeilberger}}{,}{\mathrm{abelsol}}{,}{\mathrm{adjoint}}{,}{\mathrm{autonomous}}{,}{\mathrm{bernoullisol}}{,}{\mathrm{buildsol}}{,}{\mathrm{buildsym}}{,}{\mathrm{canoni}}{,}{\mathrm{caseplot}}{,}{\mathrm{casesplit}}{,}{\mathrm{checkrank}}{,}{\mathrm{chinisol}}{,}{\mathrm{clairautsol}}{,}{\mathrm{constcoeffsols}}{,}{\mathrm{convertAlg}}{,}{\mathrm{convertsys}}{,}{\mathrm{dalembertsol}}{,}{\mathrm{dcoeffs}}{,}{\mathrm{de2diffop}}{,}{\mathrm{dfieldplot}}{,}{\mathrm{diff_table}}{,}{\mathrm{diffop2de}}{,}{\mathrm{dperiodic_sols}}{,}{\mathrm{dpolyform}}{,}{\mathrm{dsubs}}{,}{\mathrm{eigenring}}{,}{\mathrm{endomorphism_charpoly}}{,}{\mathrm{equinv}}{,}{\mathrm{eta_k}}{,}{\mathrm{eulersols}}{,}{\mathrm{exactsol}}{,}{\mathrm{expsols}}{,}{\mathrm{exterior_power}}{,}{\mathrm{firint}}{,}{\mathrm{firtest}}{,}{\mathrm{formal_sol}}{,}{\mathrm{gen_exp}}{,}{\mathrm{generate_ic}}{,}{\mathrm{genhomosol}}{,}{\mathrm{gensys}}{,}{\mathrm{hamilton_eqs}}{,}{\mathrm{hypergeometricsols}}{,}{\mathrm{hypergeomsols}}{,}{\mathrm{hyperode}}{,}{\mathrm{indicialeq}}{,}{\mathrm{infgen}}{,}{\mathrm{initialdata}}{,}{\mathrm{integrate_sols}}{,}{\mathrm{intfactor}}{,}{\mathrm{invariants}}{,}{\mathrm{kovacicsols}}{,}{\mathrm{leftdivision}}{,}{\mathrm{liesol}}{,}{\mathrm{line_int}}{,}{\mathrm{linearsol}}{,}{\mathrm{matrixDE}}{,}{\mathrm{matrix_riccati}}{,}{\mathrm{maxdimsystems}}{,}{\mathrm{moser_reduce}}{,}{\mathrm{muchange}}{,}{\mathrm{mult}}{,}{\mathrm{mutest}}{,}{\mathrm{newton_polygon}}{,}{\mathrm{normalG2}}{,}{\mathrm{ode_int_y}}{,}{\mathrm{ode_y1}}{,}{\mathrm{odeadvisor}}{,}{\mathrm{odepde}}{,}{\mathrm{parametricsol}}{,}{\mathrm{particularsol}}{,}{\mathrm{phaseportrait}}{,}{\mathrm{poincare}}{,}{\mathrm{polysols}}{,}{\mathrm{power_equivalent}}{,}{\mathrm{rational_equivalent}}{,}{\mathrm{ratsols}}{,}{\mathrm{redode}}{,}{\mathrm{reduceOrder}}{,}{\mathrm{reduce_order}}{,}{\mathrm{regular_parts}}{,}{\mathrm{regularsp}}{,}{\mathrm{remove_RootOf}}{,}{\mathrm{riccati_system}}{,}{\mathrm{riccatisol}}{,}{\mathrm{rifread}}{,}{\mathrm{rifsimp}}{,}{\mathrm{rightdivision}}{,}{\mathrm{rtaylor}}{,}{\mathrm{separablesol}}{,}{\mathrm{singularities}}{,}{\mathrm{solve_group}}{,}{\mathrm{super_reduce}}{,}{\mathrm{symgen}}{,}{\mathrm{symmetric_power}}{,}{\mathrm{symmetric_product}}{,}{\mathrm{symtest}}{,}{\mathrm{transinv}}{,}{\mathrm{translate}}{,}{\mathrm{untranslate}}{,}{\mathrm{varparam}}{,}{\mathrm{zoom}}\right]$ (8)
 • As an example, consider the following second order, nonlinear ODE.
 > ode := x^4 * diff( y( x ), x, x ) + ( x * diff( y( x ), x ) - y( x ) )^3 = 0;
 ${\mathrm{ode}}{≔}{{x}}^{{4}}{}\left(\frac{{{ⅆ}}^{{2}}}{{ⅆ}{{x}}^{{2}}}\phantom{\rule[-0.0ex]{0.4em}{0.0ex}}{y}{}\left({x}\right)\right){+}{\left({x}{}\left(\frac{{ⅆ}}{{ⅆ}{x}}\phantom{\rule[-0.0ex]{0.4em}{0.0ex}}{y}{}\left({x}\right)\right){-}{y}{}\left({x}\right)\right)}^{{3}}{=}{0}$ (9)
 • The new odeadvisor command, classifies this differential equation as follows
 $\left[\left[{\mathrm{_2nd_order}}{,}{\mathrm{_with_linear_symmetries}}\right]\right]$ (10)
 • Given the additional, optional argument help, odeadvisor will pop up a related help page.
 $\left[\left[{\mathrm{_2nd_order}}{,}{\mathrm{_with_linear_symmetries}}\right]\right]$ (11)
 • The result from odeadvisor indicates that this is a second order ODE with linear symmetries. You can see the symmetries of this ODE using the symgen command (see DEtools,Lie)
 > symgen( ode );
 $\left[{\mathrm{_ξ}}{=}{0}{,}{\mathrm{_η}}{=}{x}\right]{,}\left[{\mathrm{_ξ}}{=}{x}{,}{\mathrm{_η}}{=}{y}\right]$ (12)
 • The dsolve command, based on this information, will solve this ODE as follows (see dsolve,Lie)
 > dsolve( ode );
 ${y}{}\left({x}\right){=}\left({-}{\mathrm{arctan}}{}\left(\frac{{1}}{\sqrt{{\mathrm{_C1}}{}{{x}}^{{2}}{-}{1}}}\right){+}{\mathrm{_C2}}\right){}{x}{,}{y}{}\left({x}\right){=}\left({\mathrm{arctan}}{}\left(\frac{{1}}{\sqrt{{\mathrm{_C1}}{}{{x}}^{{2}}{-}{1}}}\right){+}{\mathrm{_C2}}\right){}{x}$ (13)
 • Most of the steps of the symmetry scheme are available as user-level commands. Consider for instance the symmetry cycle.
 1) A pair of infinitesimals:
 > sym := [_xi = 0, _eta = exp(y)/ln(x)];
 ${\mathrm{sym}}{≔}\left[{\mathrm{_ξ}}{=}{0}{,}{\mathrm{_η}}{=}\frac{{{ⅇ}}^{{y}}}{{\mathrm{ln}}{}\left({x}\right)}\right]$ (14)
 2) The most general first order ODE invariant under the symmetry group represented by the infinitesimals above can be obtained using equinv
 > ODE := equinv( sym, y(x) );
 ${\mathrm{ODE}}{≔}\frac{{ⅆ}}{{ⅆ}{x}}\phantom{\rule[-0.0ex]{0.4em}{0.0ex}}{y}{}\left({x}\right){=}\frac{{1}}{{\mathrm{ln}}{}\left({x}\right){}{x}}{+}{{ⅇ}}^{{y}{}\left({x}\right)}{}{\mathrm{_F1}}{}\left({x}\right)$ (15)
 3) This ODE can then be solved by dsolve which calls symgen to determine the ODE symmetries and uses this information to arrive at
 > ans := dsolve( ODE );
 ${\mathrm{ans}}{≔}{y}{}\left({x}\right){=}{-}{\mathrm{ln}}{}\left({-}\frac{{\int }{\mathrm{ln}}{}\left({x}\right){}{\mathrm{_F1}}{}\left({x}\right)\phantom{\rule[-0.0ex]{0.3em}{0.0ex}}{ⅆ}{x}{+}{\mathrm{_C1}}}{{\mathrm{ln}}{}\left({x}\right)}\right)$ (16)
 4) The infinitesimals of the symmetry group can in turn be reobtained departing from the solution above using buildsym
 > buildsym(ans, y(x));
 $\left[{\mathrm{_ξ}}{=}{0}{,}{\mathrm{_η}}{=}\frac{{{ⅇ}}^{{y}}}{{\mathrm{ln}}{}\left({x}\right)}\right]$ (17)
 5) The concrete Lie group of transformation equations (changes of variables) which leaves the ODE invariant can be obtained using transinv
 > TR_1 := transinv( sym, y(x), s(r) );
 ${\mathrm{TR_1}}{≔}\left\{{r}{=}{x}{,}{s}{}\left({r}\right){=}{\mathrm{ln}}{}\left({-}\frac{{\mathrm{ln}}{}\left({x}\right)}{{\mathrm{_α}}{}{{ⅇ}}^{{y}{}\left({x}\right)}{-}{\mathrm{ln}}{}\left({x}\right)}\right){+}{y}{}\left({x}\right)\right\}$ (18)
 In the above, _alpha; is the continuous parameter of the Lie group (that is, a real constant). The inverse transformation is given by
 > ITR_1 := solve(TR_1,{x,y(x)});
 ${\mathrm{ITR_1}}{≔}\left\{{x}{=}{r}{,}{y}{}\left({x}\right){=}{s}{}\left({r}\right){-}{\mathrm{ln}}{}\left(\frac{{{ⅇ}}^{{s}{}\left({r}\right)}{}{\mathrm{_α}}{+}{\mathrm{ln}}{}\left({r}\right)}{{\mathrm{ln}}{}\left({r}\right)}\right)\right\}$ (19)
 and can be used to check that the ODE is actually invariant under these transformation equations, arriving at an ODE with the same form as the original one (using dchange to change variables):
 > PDEtools[dchange](ITR_1, ODE, [r,s(r)], normal);
 $\frac{\left(\frac{{ⅆ}}{{ⅆ}{r}}\phantom{\rule[-0.0ex]{0.4em}{0.0ex}}{s}{}\left({r}\right)\right){}{{\mathrm{ln}}{}\left({r}\right)}^{{2}}{}{r}{+}{{ⅇ}}^{{s}{}\left({r}\right)}{}{\mathrm{_α}}}{{\mathrm{ln}}{}\left({r}\right){}{r}{}\left({{ⅇ}}^{{s}{}\left({r}\right)}{}{\mathrm{_α}}{+}{\mathrm{ln}}{}\left({r}\right)\right)}{=}\frac{{{ⅇ}}^{{s}{}\left({r}\right){-}{\mathrm{ln}}{}\left(\frac{{{ⅇ}}^{{s}{}\left({r}\right)}{}{\mathrm{_α}}{+}{\mathrm{ln}}{}\left({r}\right)}{{\mathrm{ln}}{}\left({r}\right)}\right)}{}{\mathrm{_F1}}{}\left({r}\right){}{r}{}{\mathrm{ln}}{}\left({r}\right){+}{1}}{{r}{}{\mathrm{ln}}{}\left({r}\right)}$ (20)
 > expand(simplify(solve((20),{diff(s(r),r)})));
 $\left\{\frac{{ⅆ}}{{ⅆ}{r}}\phantom{\rule[-0.0ex]{0.4em}{0.0ex}}{s}{}\left({r}\right){=}{\mathrm{_F1}}{}\left({r}\right){}{{ⅇ}}^{{s}{}\left({r}\right)}{+}\frac{{1}}{{\mathrm{ln}}{}\left({r}\right){}{r}}\right\}$ (21)
 6) The canonical coordinates of this Lie group (the coordinates which reduce this ODE to a quadrature; see odeadvisor,quadrature) are obtained using canoni
 > TR_2 := canoni(sym,y(x),s(r));
 ${\mathrm{TR_2}}{≔}\left\{{r}{=}{x}{,}{s}{}\left({r}\right){=}{-}\frac{{\mathrm{ln}}{}\left({x}\right)}{{{ⅇ}}^{{y}{}\left({x}\right)}}\right\}$ (22)
 > ITR_2 := solve(TR_2,{x,y(x)});
 ${\mathrm{ITR_2}}{≔}\left\{{x}{=}{r}{,}{y}{}\left({x}\right){=}{\mathrm{ln}}{}\left({-}\frac{{\mathrm{ln}}{}\left({r}\right)}{{s}{}\left({r}\right)}\right)\right\}$ (23)
 These canonical coordinates are presently used by dsolve to reduce ODE to a quadrature by change of variables
 > PDEtools[dchange](ITR_2,ODE,[r,s(r)],normal);
 $\frac{{-}\left(\frac{{ⅆ}}{{ⅆ}{r}}\phantom{\rule[-0.0ex]{0.4em}{0.0ex}}{s}{}\left({r}\right)\right){}{\mathrm{ln}}{}\left({r}\right){}{r}{+}{s}{}\left({r}\right)}{{s}{}\left({r}\right){}{r}{}{\mathrm{ln}}{}\left({r}\right)}{=}\frac{{-}{{\mathrm{ln}}{}\left({r}\right)}^{{2}}{}{\mathrm{_F1}}{}\left({r}\right){}{r}{+}{s}{}\left({r}\right)}{{s}{}\left({r}\right){}{r}{}{\mathrm{ln}}{}\left({r}\right)}$ (24)
 > expand(simplify(solve((24),{diff(s(r),r)})));
 $\left\{\frac{{ⅆ}}{{ⅆ}{r}}\phantom{\rule[-0.0ex]{0.4em}{0.0ex}}{s}{}\left({r}\right){=}{\mathrm{ln}}{}\left({r}\right){}{\mathrm{_F1}}{}\left({r}\right)\right\}$ (25)
 Once the right hand side of the ODE above does not depend on s(r), it is a quadrature and is solved just integrating both sides with respect to r. Changing variables back one arrives at the answer for the original ODE returned by dsolve.
 7) Finally, the infinitesimals of an underlying symmetry group can be used to build an integrating factor for this first order ODE (see odeadvisor,exact) by using the intfactor command:
 > ODE;
 $\frac{{ⅆ}}{{ⅆ}{x}}\phantom{\rule[-0.0ex]{0.4em}{0.0ex}}{y}{}\left({x}\right){=}\frac{{1}}{{\mathrm{ln}}{}\left({x}\right){}{x}}{+}{{ⅇ}}^{{y}{}\left({x}\right)}{}{\mathrm{_F1}}{}\left({x}\right)$ (26)
 > mu := intfactor(ODE);
 ${\mathrm{\mu }}{≔}{{ⅇ}}^{{-}{y}{}\left({x}\right)}{}{\mathrm{ln}}{}\left({x}\right)$ (27)
 > odeadvisor( mu * ODE );
 $\left[{\mathrm{_exact}}{,}\left[{\mathrm{_1st_order}}{,}{\mathrm{_with_symmetry_\left[F\left(x\right),G\left(x\right)\right]}}\right]\right]$ (28)
 • There are a variety of optional arguments to dsolve (see the dsolve,Lie for details).

PDEtools

 The PDEtools package is a new package in Maple. PDEtools is a collection of commands and routines for finding analytical solutions for partial differential equations (PDEs). The package is an implementation of known methods for solving PDEs; however, it also allows you to look for solutions of equations not yet automatically solved by the package, or for "different solutions" when the package returns a solution which is not the most general one. For this purpose, you can make use of the dchange command and of the HINT option of the pdsolve command (especially the functional hint), both explained in more detail in the corresponding help pages. Finally, PDEtools incorporates the PDEplot command, for plotting the solution for linear and nonlinear first order PDEs with given initial conditions.
 > with(PDEtools);
 $\left[{\mathrm{CanonicalCoordinates}}{,}{\mathrm{ChangeSymmetry}}{,}{\mathrm{CharacteristicQ}}{,}{\mathrm{CharacteristicQInvariants}}{,}{\mathrm{ConservedCurrentTest}}{,}{\mathrm{ConservedCurrents}}{,}{\mathrm{ConsistencyTest}}{,}{\mathrm{D_Dx}}{,}{\mathrm{DeterminingPDE}}{,}{\mathrm{Eta_k}}{,}{\mathrm{Euler}}{,}{\mathrm{FirstIntegralSolver}}{,}{\mathrm{FromJet}}{,}{\mathrm{FunctionFieldSolutions}}{,}{\mathrm{InfinitesimalGenerator}}{,}{\mathrm{Infinitesimals}}{,}{\mathrm{IntegratingFactorTest}}{,}{\mathrm{IntegratingFactors}}{,}{\mathrm{InvariantEquation}}{,}{\mathrm{InvariantSolutions}}{,}{\mathrm{InvariantTransformation}}{,}{\mathrm{Invariants}}{,}{\mathrm{Laplace}}{,}{\mathrm{Library}}{,}{\mathrm{PDEplot}}{,}{\mathrm{PolynomialSolutions}}{,}{\mathrm{ReducedForm}}{,}{\mathrm{SimilaritySolutions}}{,}{\mathrm{SimilarityTransformation}}{,}{\mathrm{Solve}}{,}{\mathrm{SymmetryCommutator}}{,}{\mathrm{SymmetryGauge}}{,}{\mathrm{SymmetrySolutions}}{,}{\mathrm{SymmetryTest}}{,}{\mathrm{SymmetryTransformation}}{,}{\mathrm{TWSolutions}}{,}{\mathrm{ToJet}}{,}{\mathrm{ToMissingDependentVariable}}{,}{\mathrm{build}}{,}{\mathrm{casesplit}}{,}{\mathrm{charstrip}}{,}{\mathrm{dchange}}{,}{\mathrm{dcoeffs}}{,}{\mathrm{declare}}{,}{\mathrm{diff_table}}{,}{\mathrm{difforder}}{,}{\mathrm{dpolyform}}{,}{\mathrm{dsubs}}{,}{\mathrm{mapde}}{,}{\mathrm{separability}}{,}{\mathrm{splitstrip}}{,}{\mathrm{splitsys}}{,}{\mathrm{undeclare}}\right]$ (29)
 • When the general solution is found, it is returned directly in equation format
 > PDE := diff(f(x,y,z),y)+diff(f(x,y,z),x)/x/z=diff(f(x,y,z),z);
 ${\mathrm{PDE}}{≔}\frac{{\partial }}{{\partial }{y}}\phantom{\rule[-0.0ex]{0.4em}{0.0ex}}{f}{}\left({x}{,}{y}{,}{z}\right){+}\frac{\frac{{\partial }}{{\partial }{x}}\phantom{\rule[-0.0ex]{0.4em}{0.0ex}}{f}{}\left({x}{,}{y}{,}{z}\right)}{{x}{}{z}}{=}\frac{{\partial }}{{\partial }{z}}\phantom{\rule[-0.0ex]{0.4em}{0.0ex}}{f}{}\left({x}{,}{y}{,}{z}\right)$ (30)
 > ans := pdsolve(PDE);
 ${\mathrm{ans}}{≔}{f}{}\left({x}{,}{y}{,}{z}\right){=}{\mathrm{_F1}}{}\left({z}{}{{ⅇ}}^{\frac{{{x}}^{{2}}}{{2}}}{,}{y}{+}{z}\right)$ (31)
 • Answers can be tested using pdetest
 > pdetest(ans, PDE);
 ${0}$ (32)
 • When the answer obtained is not the most general one, pdsolve returns using the structure of the solution, to allow the user to determine whether the answer is useful or not
 > PDE := diff(f(x,y,z),y)^2*exp(2*y)+diff(f(x,y,z),x)/cos(x)/z=diff(f(x,y,z),z);
 ${\mathrm{PDE}}{≔}{\left(\frac{{\partial }}{{\partial }{y}}\phantom{\rule[-0.0ex]{0.4em}{0.0ex}}{f}{}\left({x}{,}{y}{,}{z}\right)\right)}^{{2}}{}{{ⅇ}}^{{2}{}{y}}{+}\frac{\frac{{\partial }}{{\partial }{x}}\phantom{\rule[-0.0ex]{0.4em}{0.0ex}}{f}{}\left({x}{,}{y}{,}{z}\right)}{{\mathrm{cos}}{}\left({x}\right){}{z}}{=}\frac{{\partial }}{{\partial }{z}}\phantom{\rule[-0.0ex]{0.4em}{0.0ex}}{f}{}\left({x}{,}{y}{,}{z}\right)$ (33)
 > ans := pdsolve(PDE);
 ${\mathrm{ans}}{≔}\left({f}{}\left({x}{,}{y}{,}{z}\right){=}{\mathrm{_F1}}{}\left({x}\right){+}{\mathrm{_F2}}{}\left({y}\right){+}{\mathrm{_F3}}{}\left({z}\right)\right)\phantom{\rule[-0.0ex]{0.3em}{0.0ex}}{&where}\phantom{\rule[-0.0ex]{0.3em}{0.0ex}}\left[\left\{{\left(\frac{{ⅆ}}{{ⅆ}{y}}\phantom{\rule[-0.0ex]{0.4em}{0.0ex}}{\mathrm{_F2}}{}\left({y}\right)\right)}^{{2}}{=}{{ⅇ}}^{{-}{2}{}{y}}{}{{\mathrm{_c}}}_{{2}}{,}\frac{{ⅆ}}{{ⅆ}{x}}\phantom{\rule[-0.0ex]{0.4em}{0.0ex}}{\mathrm{_F1}}{}\left({x}\right){=}{{\mathrm{_c}}}_{{1}}{}{\mathrm{cos}}{}\left({x}\right){,}\frac{{ⅆ}}{{ⅆ}{z}}\phantom{\rule[-0.0ex]{0.4em}{0.0ex}}{\mathrm{_F3}}{}\left({z}\right){=}\frac{{{\mathrm{_c}}}_{{1}}}{{z}}{+}{{\mathrm{_c}}}_{{2}}\right\}\right]$ (34)
 That is, on the left is the result found for the indeterminate function, and on the right is a list. In this case, the list contains a set of ODEs for the functions _F1, _F2 and _F3, introduced by pdsolve when building the result. In other examples the list may contain, additionally, an indication of any arbitrary functions and/or change of variables introduced during the solving process. To see the resulting expression for the indeterminate function f(x,y,z), it is possible to use the build command:
 > build(ans);
 ${f}{}\left({x}{,}{y}{,}{z}\right){=}{{\mathrm{_c}}}_{{1}}{}{\mathrm{sin}}{}\left({x}\right){+}{\mathrm{_C1}}{-}\sqrt{\frac{{{\mathrm{_c}}}_{{2}}}{{\left({{ⅇ}}^{{y}}\right)}^{{2}}}}{+}{\mathrm{_C2}}{+}{{\mathrm{_c}}}_{{1}}{}{\mathrm{ln}}{}\left({z}\right){+}{{\mathrm{_c}}}_{{2}}{}{z}{+}{\mathrm{_C3}}$ (35)
 • A suitable change of variables is the most 'powerful' method when the solution cannot be found by other means. These changes or variables can now be performed using dchange. As a blackboard example, consider for instance the reduction of the number of differentiation variables in a given PDE
 > PDE := 1+F(x,y)^2+y*diff(F(x,y),x)-x*diff(F(x,y),y);
 ${\mathrm{PDE}}{≔}{1}{+}{{F}{}\left({x}{,}{y}\right)}^{{2}}{+}{y}{}\left(\frac{{\partial }}{{\partial }{x}}\phantom{\rule[-0.0ex]{0.4em}{0.0ex}}{F}{}\left({x}{,}{y}\right)\right){-}{x}{}\left(\frac{{\partial }}{{\partial }{y}}\phantom{\rule[-0.0ex]{0.4em}{0.0ex}}{F}{}\left({x}{,}{y}\right)\right)$ (36)
 The solution to the PDE above is in fact invariant under rotations in the plane, which means that introducing polar coordinates (the natural coordinates for describing rotations) we will obtain the aforementioned reduction
 > TR := {x=r*cos(phi), y=r*sin(phi)};
 ${\mathrm{TR}}{≔}\left\{{x}{=}{r}{}{\mathrm{cos}}{}\left({\mathrm{\phi }}\right){,}{y}{=}{r}{}{\mathrm{sin}}{}\left({\mathrm{\phi }}\right)\right\}$ (37)
 > dchange(TR, PDE, simplify);
 ${1}{+}{{F}{}\left({\mathrm{\phi }}{,}{r}\right)}^{{2}}{-}\frac{{\partial }}{{\partial }{\mathrm{\phi }}}\phantom{\rule[-0.0ex]{0.4em}{0.0ex}}{F}{}\left({\mathrm{\phi }}{,}{r}\right)$ (38)
 The resulting PDE is easily solvable
 > ans := pdsolve((38));
 ${\mathrm{ans}}{≔}{F}{}\left({\mathrm{\phi }}{,}{r}\right){=}{\mathrm{tan}}{}\left({\mathrm{\phi }}{+}{\mathrm{_F1}}{}\left({r}\right)\right)$ (39)
 and the answer to the original problem can be obtained changing variables back
 > ITR := {r=sqrt(x^2+y^2), phi=arctan(y/x)};
 ${\mathrm{ITR}}{≔}\left\{{\mathrm{\phi }}{=}{\mathrm{arctan}}{}\left(\frac{{y}}{{x}}\right){,}{r}{=}\sqrt{{{x}}^{{2}}{+}{{y}}^{{2}}}\right\}$ (40)
 > dchange(ITR, ans, known=_F1, simplify);
 ${F}{}\left({x}{,}{y}\right){=}{\mathrm{tan}}{}\left({\mathrm{arctan}}{}\left(\frac{{y}}{{x}}\right){+}{\mathrm{_F1}}{}\left(\sqrt{{{x}}^{{2}}{+}{{y}}^{{2}}}\right)\right)$ (41)
 > pdetest((41),PDE);
 ${0}$ (42)
 • dchange is a general change of variables command and as such it can be used to change variables in procedures directly or in integrals (actually any valid Maple expression; see the related help page).

Three Dimensional Geometry

 An extensive set of facilities for working with three-dimensional geometric objects and algorithms is provided in the new geom3d package.
 Using the geom3d package, you can manipulate a wide variety of geometric objects, including points, lines, planes, spheres, polyhedra, and other solids.
 Use the geom3d package by entering the with command.  You can refer to procedures in the package by their short names.
 > restart;
 > with( geom3d ):
 • It is very easy to create a variety of geometric objects.
 > tetrahedron( T, point( O, 0, 0, 0 ), 3 );
 ${T}$ (43)
 > faces( T );
 $\left[\left[\left[\sqrt{{3}}{,}\sqrt{{3}}{,}\sqrt{{3}}\right]{,}\left[\sqrt{{3}}{,}{-}\sqrt{{3}}{,}{-}\sqrt{{3}}\right]{,}\left[{-}\sqrt{{3}}{,}\sqrt{{3}}{,}{-}\sqrt{{3}}\right]\right]{,}\left[\left[\sqrt{{3}}{,}\sqrt{{3}}{,}\sqrt{{3}}\right]{,}\left[{-}\sqrt{{3}}{,}{-}\sqrt{{3}}{,}\sqrt{{3}}\right]{,}\left[\sqrt{{3}}{,}{-}\sqrt{{3}}{,}{-}\sqrt{{3}}\right]\right]{,}\left[\left[\sqrt{{3}}{,}\sqrt{{3}}{,}\sqrt{{3}}\right]{,}\left[{-}\sqrt{{3}}{,}\sqrt{{3}}{,}{-}\sqrt{{3}}\right]{,}\left[{-}\sqrt{{3}}{,}{-}\sqrt{{3}}{,}\sqrt{{3}}\right]\right]{,}\left[\left[\sqrt{{3}}{,}{-}\sqrt{{3}}{,}{-}\sqrt{{3}}\right]{,}\left[{-}\sqrt{{3}}{,}{-}\sqrt{{3}}{,}\sqrt{{3}}\right]{,}\left[{-}\sqrt{{3}}{,}\sqrt{{3}}{,}{-}\sqrt{{3}}\right]\right]\right]$ (44)
 > area( T );
 ${24}{}\sqrt{{3}}$ (45)
 > volume( T );
 ${8}{}\sqrt{{3}}$ (46)
 • You can visualize geometric objects using the draw command.
 > draw( T );
 • See the list of example worksheets for example worksheets available for this package.

Strings

 True strings are added to Maple V Release 5.  Previously, names also acted as strings when necessary.
 • Strings and names are identified with a different syntax:
 > s := "This is a string";
 ${s}{≔}{"This is a string"}$ (47)
 > type( s, 'string' );
 ${\mathrm{true}}$ (48)
 > type( s, 'name' );
 ${\mathrm{false}}$ (49)
 > n := This is a name;
 ${n}{≔}{\mathrm{This is a name}}$ (50)
 > type( n, 'string' );
 ${\mathrm{false}}$ (51)
 > type( n, 'name' );
 ${\mathrm{true}}$ (52)
 • A fundamental distinction between names and strings is that names may be assigned a value, while strings cannot.
 > A name := 5;
 ${\mathrm{A name}}{≔}{5}$ (53)
 > "A string" := 5;
 • Many procedures which formerly took names or strings as parameters, or returned names for use as strings, now will accept strings (and names), and return strings.
 > save A name, "/tmp/junk.m";
 > printf( "%s: %d\n", "A String of length: ", length( "A String of length: " ) );
 A String of length: : 20
 The MATLAB® Link allows you to open a connection to the MATLAB® numeric software package, and carry out computations there, returning the results to your current Maple session.
 • To use this package, you must have a correctly installed, licensed copy of MATLAB® on your computer. The Matlab example worksheet provides further explanation and examples. (Note: you will need MATLAB® to execute this worksheet.)
 Example Computation
 To establish a connection with MATLAB®, and to make available the Maple commands for interacting with it, use the with command to load the Matlab package.
 > with( Matlab ):
 First, define a four by four Maple matrix.  Use the Maple command below.
 > m := linalg[ 'randmatrix' ]( 4, 4 );
 ${m}{≔}\left[\begin{array}{cccc}{-7}& {22}& {-55}& {-94}\\ {87}& {-56}& {0}& {-62}\\ {97}& {-73}& {-4}& {-83}\\ {-10}& {62}& {-82}& {80}\end{array}\right]$ (54)
 To define a MATLAB® variable, use the procedure setvar.
 > setvar( "m", m );
 The MATLAB® variable "m" is defined to have the same value as the Maple variable m. Note that the variable "m" now exists in the current MATLAB® session to which Maple is connected.
 Compute the Schur decomposition of this matrix m in MATLAB® by issuing the command
 > evalM( "r = schur( m )" );
 Note the distinction between the evalM command and Maple's matrix evaluator, evalm.
 This command sends the MATLAB® command enclosed in quotation marks to the running MATLAB® session to be executed. In this case, a MATLAB® variable "r" is assigned the value of the Schur decomposition of the MATLAB® variable "m".
 Now retrieve the value of "r" from MATLAB®, using the getvar command.
 > s := getvar( "r" );
 Finally, to convert this to a Maple matrix, use the command
 > a := evalm( convert( s, 'array' ) );

Arrays of Hardware Floats

 Arrays of hardware floating point numbers have been added to Maple V Release 5. Using arrays of hardware floating point numbers (called hfarrays in Maple) can dramatically improve the performance of numerical algorithms.
 If you write a procedure that will be evaluated within evalhf, be careful not to introduce any symbolic constructs.
 A simple, but nontrivial example of hfarrays is an implementation of the forward elimination'' algorithm employed by traditional Gaussian Elimination for square numerical matrices. The main departure from the straightforward description of the algorithm is that we take a little care to choose our pivot in a way that helps to proscribe numerical instability.
 > macro( forelim = HFGaussElim/forelim );
 ${\mathrm{forelim}}$ (55)
 > forelim :=      proc(r::posint, m::{array,hfarray})     local   i, j, k,        # indices             max,            # used to choose the pivot row             t;              # temporary for swapping     # for each row     for i from 1 to r do         max := i;         # find the pivot row         # (should be modified for sparse implementation)         for j from 1 + i to r do             if abs( m[ j, i ] ) > abs( m[ max, i ] ) then                 max := j;             fi;         od;         # interchange         for k from i to r do             # swap             t := m[ i, k ];             m[ i, k ] := m[ max, k ];             m[ max, k ] := t;         od;         # do the pivot         for j from 1 + i to r do             for k from r to i by -1 do                 m[ j, k ] := m[ j, k ] - m[ i, k ] * m[ j, i ] / m[ i, i ];             od;         od;     od;     m; end;
 ${\mathrm{HFGaussElim/forelim}}{:=}{\mathbf{proc}}\left({r}{::}{\mathrm{posint}}{,}{m}{::}\left\{{\mathrm{array}}{,}{\mathrm{hfarray}}\right\}\right)\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{local}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{i}{,}{j}{,}{k}{,}{\mathrm{max}}{,}{t}{;}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{for}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{i}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{to}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{r}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{do}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathrm{max}}{:=}{i}{;}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{for}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{j}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{from}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{i}{+}{1}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{to}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{r}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{do}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{if}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathrm{abs}}{}\left({m}{[}{\mathrm{max}}{,}{i}{]}\right){<}{\mathrm{abs}}{}\left({m}{[}{j}{,}{i}{]}\right)\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{then}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathrm{max}}{:=}{j}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{end if}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{end do}}{;}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{for}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{k}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{from}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{i}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{to}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{r}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{do}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{t}{:=}{m}{[}{i}{,}{k}{]}{;}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{m}{[}{i}{,}{k}{]}{:=}{m}{[}{\mathrm{max}}{,}{k}{]}{;}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{m}{[}{\mathrm{max}}{,}{k}{]}{:=}{t}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{end do}}{;}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{for}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{j}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{from}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{i}{+}{1}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{to}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{r}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{do}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{for}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{k}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{from}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{r}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{by}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{−}{1}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{to}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{i}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{do}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{m}{[}{j}{,}{k}{]}{:=}{m}{[}{j}{,}{k}{]}{-}{m}{[}{i}{,}{k}{]}{*}{m}{[}{j}{,}{i}{]}{/}{m}{[}{i}{,}{i}{]}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{end do}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{end do}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{end do}}{;}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{m}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}{\mathbf{end proc}}$ (56)
 • Given a square matrix as input, an upper triangular matrix, row- equivalent to the input, is produced.
 > forelim( 4, matrix( 4, 4, [ 1, 2, 3, 4, 2, 3, 4, 1, 3, 4, 1, 2, 4, 1, 2, 3 ] ) );
 $\left[\begin{array}{cccc}{4}& {1}& {2}& {3}\\ {0}& \frac{{13}}{{4}}& {-}\frac{{1}}{{2}}& {-}\frac{{1}}{{4}}\\ {0}& {0}& \frac{{44}}{{13}}& {-}\frac{{4}}{{13}}\\ {0}& {0}& {0}& \frac{{40}}{{11}}\end{array}\right]$ (57)
 • Now we can wrap forelim in a procedure HFGaussElim that checks its arguments and evaluates forelim with the evalhf environment.
 > HFGaussElim     :=      proc(m::matrix)     local   rows, cols, i, j, lm;     rows := linalg[ 'rowdim' ]( m );     cols := linalg[ 'coldim' ]( m );     if rows <> cols then             ERROR( "Must be a square matrix" );     fi;     lm := matrix( rows, rows );