/** * Determines the version of the underlying maxima version. * * @return An array of 3 elements, containing, major, minor and build version number, * respectively. * @throws MaximaTimeoutException */ private int[] determineMaximaVersion() throws MaximaTimeoutException { String buildinfo = ggbMaxima.executeCall("build_info();"); int[] retval = new int[3]; Pattern p = Pattern.compile("Maxima version: (\\d+).(\\d+).(\\d+)"); Matcher m = p.matcher(buildinfo); if (!m.find()) retval[0] = retval[1] = retval[2] = -1; else { retval[0] = Integer.parseInt(m.group(1)); retval[1] = Integer.parseInt(m.group(2)); retval[2] = Integer.parseInt(m.group(3)); } return retval; }
private void initMyMaximaFunctions() throws MaximaTimeoutException, geogebra.cas.jacomax.MaximaTimeoutException { // turn auto-simplification off, so a+a gives a+a // with this setting ev( a+a, simp ) is needed to get 2*a ggbMaxima.executeCall("simp:false;"); // variable ordering: then factor(a^2-b^2) gives (a-b)*(b+a) instead of �(b-a)(b+a) // see http://www.geogebra.org/trac/ticket/281 ggbMaxima.executeCall("ordergreat(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,z);"); // set line length of "terminal" // we don't want lines broken ggbMaxima.executeCall("linel:10000;"); // make sure results are returned ggbMaxima.executeCall("display2d:false;"); // make sure integral(1/x) = log(abs(x)) ggbMaxima.executeCall("logabs:true;"); // make sure algsys (solve) doesn't return complex roots ggbMaxima.executeCall("realonly:true;"); // eg x^-1 displayed as 1/x ggbMaxima.executeCall("exptdispflag:true;"); // suppresses the printout of the message informing the user of the conversion of floating point // numbers to rational numbers ggbMaxima.executeCall("ratprint:false;"); // When true, r some rational number, and x some expression, %e^(r*log(x)) will be simplified // into x^r . It should be noted that the radcan command also does this transformation, and more // complicated transformations of this ilk as well. The logcontract command "contracts" // expressions containing log. ggbMaxima.executeCall("%e_to_numlog:true;"); // define custom functions ggbMaxima.executeCall("log10(x) := log(x) / log(10);"); ggbMaxima.executeCall("log2(x) := log(x) / log(2);"); ggbMaxima.executeCall("cbrt(x) := x^(1/3);"); // needed to define lcm() ggbMaxima.executeCall("load(functs)$"); // needed for degree() ggbMaxima.executeCall("load(powers)$"); // needed for ??? ggbMaxima.executeCall("load(format)$"); // turn {x=3} into {3} etc ggbMaxima.executeCall( "stripequals(ex):=block(" + "if atom(ex) then return(ex)" + "else if op(ex)=\"=\" then return(stripequals(rhs(ex)))" + "else apply(op(ex),map(stripequals,args(ex)))" + ")$"); /* This function takes an expression ex and returns a list of coefficients of v */ ggbMaxima.executeCall( "coefflist(ex,v):= block([deg,kloop,cl]," + "cl:[]," + "ex:ev(expand(ex),simp)," + "deg:degree(ex,v)," + "ev(for kloop:0 thru deg do\n" + "cl:append(cl,[coeff(ex,v,kloop)]),simp)," + "cl" + ")$"); /* * Tests if a given symbol is a function-symbol (function name) * Implemented as LISP-function as you cannot do this with maxima-functions */ ggbMaxima.executeCall( ":lisp (defun $myfun (sym) " + "(cond ((fboundp sym)) ((get sym 'mprops) t) (t nil)))"); /* * Takes a symbol and tests if a it is already bound to something. * ( = bound to a function-name or a variable-name). * Note: weird formal parameter name as due to maxima's dynamic scoping rules * using a "normal" formal parameter just doesn't work. * (just try changing "ggbnsrphdbgse5tfd" and then call "issymbolbound('x)") */ ggbMaxima.executeCall( "issymbolbound(ggbnsrphdbgse5tfd):= " + "myfun(ggbnsrphdbgse5tfd) " + "or ?boundp(ggbnsrphdbgse5tfd);"); /* * eg integrate(x^n,x) asks if n+1 is zero * this disables the interactivity * but we get: * if equal(n+1,0) then log(abs(x)) else x^(n+1)/(n+1) * TODO: change to ggb syntax */ ggbMaxima.executeCall("load(\"noninteractive\");"); // define Degree ggbMaxima.executeCall("Degree:180/%pi;"); }