#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++# # FILE : maple.mu - a library for calling Maple slaves # # AUTHOR : Andreas Sorgatz (andi@uni-paderborn.de) # # STATUS : experimental !! (tested with MuPAD 1.3.0 and Maple V Release 4) # # SYSTEMS: UNIX versions of MuPAD # # DATE : 30.01.96 # # CHANGED: 31.01.96 - prepared for ftp server (release 1.2.2, 1.2.2a) # # CHANGED: 19.11.96 - prepared for ftp server (release 1.2.9a, 1.3) # # CHANGED: 17.02.98 - tested with Maple V.4, file was renamed # # # # This library package provides a set of functions to start a 'Maple' slave # # and to install a string based communication to it. Because of the similarity # # of the 'Maple' and 'MuPAD' syntax most expression can be exchanged without # # any translation. In most cases only the 'MuPAD' functions 'text2expr' and # # 'expr2text' are needed to convert algebraic expressions. # # # # By now this package supports only one 'Maple' slave at the time. To use the # # packages you need a MuPAD version that supports dynamic modules. This can be # # checked by executing the command "loadmod();" (release 1.2.2 or later). This # # function call should return "TRUE", otherwise this feature is not supported # # in your version. 'maple.mu' uses the dynamic modules 'slave' and 'string' . # # Both are distributed with MuPAD versions that support this feature (refer to # # $MuPAD_ROOT_PATH/`sysinfo`/modules). # # # # Dynamic modules are not documented in the MuPAD user's manual. So far there # # are some information and further examples available on our WWW server at # # http://math-www.uni-paderborn.de/MuPAD/PAPERS/MODULES . Further english # # documentation is planned for the winter 1997. # # # # KNOWN BUGS: # # # # * Using the function 'maple::eval(expr)' or simply 'maple(expr)' , 'expr' # # must not evaluate to a string. MuPAD tries to convert it to an expres- # # sion which may not make sense. This function is intend to solve/return # # algebraic expressions. # # # # * On some operating systems there seems to be problems with killing slave # # processes with active pipes. After 'maple::close()' there may be still # # a maple zombie process. # # # # If there are any problems or questions, please contact andi@uni-paderborn.de # #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++# #++ USER FUNCTIONS: open() - start the Maple slave close() - close the Maple slave put(strg) - send a string to the Maple slave get() - receive a string from the Maple slave eval(expr) - let Maple evaluate a given expression new(expr) - == eval EXAMPLES: andi> mupad *----* MuPAD 1.2.2a -- Multi Processing Algebra Data Tool /| /| *----* | Copyright (c) 1992-95 by B. Fuchssteiner, Automath | *--|-* University of Paderborn. All rights reserved. |/ |/ *----* Unregistered version, please register with MuPAD-distribution@uni-paderborn.de >> read("maple.mu"): >> maple::open(): Starting Maple ... Initializing Maple ... Ready. >> maple::put("interface(version);\n"): >> maple::data(); 61 >> maple::get(); "Maple V, Release 3, SUN SPARC SOL23, Mar 3 1994, CAMPUS WIDE\n" >> maple( int(x^3*sin(x), x) ); 3 2 - x cos(x) + 3 x sin(x) - 6 sin(x) + 6 x cos(x) >> diff(%,x); 3 x sin(x) >> >> maple::close(): >> quit ++# #------------------------------------------------------------------------------# if(op(version(),2) > 2 ) then maple:= domain("maple"): else maple:= domain(): end_if: maple::name:= "maple": maple::info:= "Library 'maple': Communication with an external Maple slave": maple::interface:= { hold(open), hold(close), hold(put), hold(get), hold(data), hold(eval) }: maple::MAPLE := "maple": # name of the Maple program # maple::NO_TIMEOUT:= TRUE: # wait until Maple sends an answer # maple::TIMEOUT := 10: # wait only N seconds for an answer # maple::sdesc := []: # slave descriptor for maple # maple::last := "": #------------------------------------------------------------------------------# #++ open - start a Maple slave open() ++# maple::open := proc( ) local command, i, PRETTY_PRINT; begin if( sysname() <> "UNIX" ) then errro( "Sorry, only supported on UNIX systems" ); end_if; if( loadmod() <> TRUE ) then error( "Sorry, dynamic modules are not supported ". "in this MuPAD version" ); end_if; if( maple::sdesc <> [] ) then error( "Use 'maple::close()' to close the current slave" ); end_if; PRETTY_PRINT:= FALSE; #++ Check arguments and generate command-string to call Maple +++++++++# if ( args(0) <> 1 ) then #++ Call "maple" on local host +++++++++++# cmd:= maple::MAPLE; end_if; #++ Start and initialize the Maple slave ++++++++++++++++++++++++++++++# print( Unquoted, "Starting Maple ..." ); maple::sdesc:= external("open","slave")( cmd ); #++ Wait for Maple startup-message ++++++++++++++++++++++++++++# if( external("timeout","slave")(maple::sdesc,maple::TIMEOUT) ) then external("close","slave")( maple::sdesc ); error( "No answer from Maple, can't continue" ); end_if; #++ Send commands for initialisation ++++++++++++++++++++++++++# print( Unquoted, "Initializing Maple ..." ); maple::put( "interface( prettyprint=0 );\n". "interface( echo=0 );\n". "interface( quiet=true );\n". "1;\n" ): #++ Wait for Maple's answers and remove them all ++++++++++++++# if( external("timeout","slave")(maple::sdesc,maple::TIMEOUT) ) then external("close","slave")( maple::sdesc ); error( "No answer from Maple, can't continue" ); end_if; maple::last:= maple::get(); print( Unquoted, "Ready." ); end_proc: #------------------------------------------------------------------------------# #++ close - close the Maple slave close() ++# maple::close := proc( ) begin if( maple::sdesc = [] ) then error( "There's currently no Maple slave open" ); end_if; external("close","slave")( maple::sdesc ); maple::sdesc:= []; null(); end_proc: #------------------------------------------------------------------------------# #++ put - send a string to Maple put( string ) string - Maple command, terminated with ";\n" ++# maple::put := proc( strg ) local len; begin if( sysname() <> "UNIX" ) then errro( "Sorry, only supported on UNIX systems" ); end_if; if( args(0) <> 1 or domtype(strg) <> DOM_STRING ) then error( "String expected" ); end_if; len:= external("put","slave")( maple::sdesc, strg ); if( len = 0 ) then error( "Can't talk to Maple" ); end_if; if( len <> strlen(strg) ) then error( "Can't talk to Maple" ); end_if; len; end_proc: #------------------------------------------------------------------------------# #++ get - receive a string from Maple get() ++# maple::get := proc( ) local timeout, answer; begin if( maple::NO_TIMEOUT ) then timeout:= 3600; else timeout:= maple::TIMEOUT; end_if; if( external("timeout","slave")(maple::sdesc,timeout) ) then error( "No answer from Maple" ); end_if; answer:= ""; repeat answer:= answer.external("get","slave")(maple::sdesc); until external("timeout","slave")(maple::sdesc,1) end_repeat; answer; end_proc: #------------------------------------------------------------------------------# #++ data - number of bytes, available from Maple data( ) ++# maple::data := proc( ) begin external("data","slave")( maple::sdesc ); end_proc: #------------------------------------------------------------------------------# #++ eval - send a MuPAD/Maple expression/command to Maple eval( expression ) expression - a MuPAD/Maple expression or function call that returns an algebraic expression. No strings are allowed as result! ++# maple::eval := proc( expre ) local output_end, buffer, result, start, end, n, no_timeout; option hold; begin maple::put( expr2text(expre).";\n" ); no_timeout:= maple::NO_TIMEOUT; maple::NO_TIMEOUT:= TRUE; if( (maple::last:= maple::get()) = "" ) then return( null() ); end_if; maple::NO_TIMEOUT:= no_timeout; result:= external("strxch","string")(maple::last, "\\\n",""); if( result = "" ) then return( null() ); end_if; eval(text2expr(result)); end_proc: #------------------------------------------------------------------------------# maple::new:= maple::eval: #------------------------------------------------------------------------------# TRUE: # end of file #