Application Center - Maplesoft

App Preview:

Java Code Generation and External Calling

You can switch back to the summary page by clicking here.

Learn about Maple
Download Application


 

Java Code Generation and External Calling in Maple 8

Copyright 2002 Waterloo Maple Inc.

A new CodeGeneration  package provides routines to translate "numeric" Maple procedures and code, such as expressions, lists, arrays, rtables, and lists of equations, to Java code.  This new package also contains improved versions of codegen[C]  and codegen[fortran] .  You now have several options to choose from when translating Maple code to Java, C or Fortran code that provide greater control over how analysis and translation of types are performed.  

Maple 8 has extended the external linking capability with the ability to link to static Java methods.

Code Generation

>    with(CodeGeneration);

[C, Fortran, Java]

Java Code Generation

The following example defines a simple procedure which returns the calculuation of x^2+y^2-z     

>    SimpleProc:=proc(x, y, z)
  return x^2+y^2-z;
end proc;

SimpleProc := proc (x, y, z) return x^2+y^2-z end proc

Using the above example, we can easily generate Java code for this procedure definition.

>    Java(SimpleProc);

class CodeGenerationClass {

  public static double SimpleProc (double x, double y, double z)

  {

    return(x * x + y * y - z);

  }

}

The CodeGeneration  package comes with numerous options to manipulate the Java code to your liking.  For example, you can use the defaulttype  option to translate all untyped parameters to integer variables.  All options used with exports in the CodeGeneration  package are described on the CodeGenerationOptions  help page.

>    Java(SimpleProc, defaulttype=integer);

class CodeGenerationClass {

  public static int SimpleProc (int x, int y, int z)

  {

    return(x * x + y * y - z);

  }

}

Create a computation sequence called cs.  

>    cs := [s=1.0+x, t=ln(x)*exp(-x), r=exp(-x)+x*t];

cs := [s = 1.0+x, t = ln(x)*exp(-x), r = exp(-x)+x*t]

CodeGeneration  interprets this as a sequence of assignments.  By including the option optimize , the Maple input is optimized before it is translated.

>    Java(cs, optimize);

s = 0.10e1 + x;

t1 = Math.log(x);

t2 = Math.exp(-x);

t = t1 * t2;

r = t2 + x * t;

Define a 5x5 matrix

>    M1:=Matrix(5, rand(25), datatype=float[8]);

M1 := Matrix(%id = 17951996)

Using the resultname  and precision  options, we specify the name of the result to be "position" and single precision to be used for floating point variables and constants.

>    Java(M1, resultname="position", precision=single);

position[0][0] = 0.6e1f;

position[0][1] = 0.20e2f;

position[0][2] = 0.22e2f;

position[0][3] = 0.13e2f;

position[0][4] = 0.1e1f;

position[1][0] = 0.13e2f;

position[1][1] = 0.10e2f;

position[1][2] = 0.18e2f;

position[1][3] = 0.21e2f;

position[1][4] = 0.9e1f;

position[2][0] = 0.5e1f;

position[2][1] = 0.13e2f;

position[2][2] = 0.7e1f;

position[2][3] = 0.10e2f;

position[2][4] = 0.24e2f;

position[3][0] = 0.10e2f;

position[3][1] = 0.16e2f;

position[3][2] = 0.11e2f;

position[3][3] = 0.7e1f;

position[3][4] = 0.24e2f;

position[4][0] = 0.11e2f;

position[4][1] = 0.23e2f;

position[4][2] = 0.16e2f;

position[4][3] = 0.9e1f;

position[4][4] = 0.23e2f;

>   

Improved C Code Generation

The following procedure returns the calculation of x*y-y*z+x*z  where x, y and z can be any type.

>    f := proc(x::float, y, z)
      return x*y-y*z+x*z;
     end proc;

f := proc (x::float, y, z) return x*y-y*z+x*z end proc

Using the above example, we can easily generate C code for this procedure definition and include the defaulttype  option to once again specify the default type of undeclared variables .

>    C(f, defaulttype=integer);

double f (double x, double y, double z)

{

  return(x * y - y * z + x * z);

}

CodeGeneration 's automatic type deduction gave parameters y and z a float type because they are in an expression involving the float variable x.  Note that the default type is assigned only to those variables left untyped by the type deduction facility.  To turn off automatic type deduction, use the deducetypes=false  option.

>    C(f, defaulttype=integer, deducetypes=false);

double f (double x, int y, int z)

{

  return(x * (double) y - (double) (y * z) + x * (double) z);

}

To turn off explicit type coercion, use the coercetypes=false  option.

>    C(f, defaulttype=integer, deducetypes=false, coercetypes=false);

double f (double x, int y, int z)

{

  return(x * y - y * z + x * z);

}

>   

Improved Fortran Code Generation

There are a number of improvements in translation to Fortran in particular, including increased support for rtables, translation of arrays with ranges not starting at 1, and the renaming of identifiers which do not satisfy the Fortran 77 standard. The following example demonstrates some of these enhancements.

>    g := proc(x::Array(numeric, 5..7))
  return x[5]+x[6]+x[7];
end proc;

g := proc (x::Array(numeric,5 .. 7)) return x[5]+x[6]+x[7] end proc

>    Fortran(g, resultname="myresult");

      doubleprecision function cg0 (x)

        doubleprecision x(5:7)

        cg0 = x(5) + x(6) + x(7)

        return

      end

>   

Code Generation and codegen

The codegen  package still offers many useful functions not yet available in CodeGeneration .  Using the CurveFitting[Spline]  routine to create a spline, a piecewise function of this spline is returned.

>    s := CurveFitting[Spline]([[0,0],[1,1],[2,4],[3,3]], v);

s := PIECEWISE([1/5*v+4/5*v^3, v < 1],[14/5-41/5*v+42/5*v^2-2*v^3, v < 2],[-114/5+151/5*v-54/5*v^2+6/5*v^3, otherwise])

Using the codegen[makeproc]  function, we can make a procedure out of this piecewise function and then use codegen[prep2trans]  to prepare this procedure so that it is in a form acceptable for translation by CodeGeneration .  

>    p1 := codegen[makeproc](s, v);

p1 := proc (v) piecewise(v < 1,1/5*v+4/5*v^3,v < 2,14/5-41/5*v+42/5*v^2-2*v^3,-114/5+151/5*v-54/5*v^2+6/5*v^3) end proc
p1 := proc (v) piecewise(v < 1,1/5*v+4/5*v^3,v < 2,14/5-41/5*v+42/5*v^2-2*v^3,-114/5+151/5*v-54/5*v^2+6/5*v^3) end proc
p1 := proc (v) piecewise(v < 1,1/5*v+4/5*v^3,v < 2,14/5-41/5*v+42/5*v^2-2*v^3,-114/5+151/5*v-54/5*v^2+6/5*v^3) end proc

>    p2 := codegen[prep2trans](p1);

p2 := proc (v) if v < 1 then 1/5*v+4/5*v^3 elif v < 2 then 14/5-41/5*v+42/5*v^2-2*v^3 else -114/5+151/5*v-54/5*v^2+6/5*v^3 end if end proc
p2 := proc (v) if v < 1 then 1/5*v+4/5*v^3 elif v < 2 then 14/5-41/5*v+42/5*v^2-2*v^3 else -114/5+151/5*v-54/5*v^2+6/5*v^3 end if end proc
p2 := proc (v) if v < 1 then 1/5*v+4/5*v^3 elif v < 2 then 14/5-41/5*v+42/5*v^2-2*v^3 else -114/5+151/5*v-54/5*v^2+6/5*v^3 end if end proc
p2 := proc (v) if v < 1 then 1/5*v+4/5*v^3 elif v < 2 then 14/5-41/5*v+42/5*v^2-2*v^3 else -114/5+151/5*v-54/5*v^2+6/5*v^3 end if end proc
p2 := proc (v) if v < 1 then 1/5*v+4/5*v^3 elif v < 2 then 14/5-41/5*v+42/5*v^2-2*v^3 else -114/5+151/5*v-54/5*v^2+6/5*v^3 end if end proc
p2 := proc (v) if v < 1 then 1/5*v+4/5*v^3 elif v < 2 then 14/5-41/5*v+42/5*v^2-2*v^3 else -114/5+151/5*v-54/5*v^2+6/5*v^3 end if end proc

Finally, we can translate this procedure to Fortran and use the declare  option to specify that parameter v should be a floating-point variable.

>    Fortran(p2, declare=[v::float]);

      doubleprecision function p2 (v)

        doubleprecision v

        doubleprecision cgret

        if (v .lt. 0.1D1)

          cgret = v / 0.5D1 + 0.4D1 / 0.5D1 * v ** 3

        else if (v .lt. 0.2D1)

          cgret = 0.14D2 / 0.5D1 - 0.41D2 / 0.5D1 * v + 0.42D2 / 0.5D1 * 

     #v ** 2 - 0.2D1 * v ** 3

        else

          cgret = -0.114D3 / 0.5D1 + 0.151D3 / 0.5D1 * v - 0.54D2 / 0.5D1

     # * v ** 2 + 0.6D1 / 0.5D1 * v ** 3

        end if

        p2 = cgret

        return

      end

>   

External Calling to Java

Calling external routines was introduced in Maple 6 with the ability to link to external C and Fortran functions.  Maple 8 has now extended this routine to call external static Java methods.

Simple Java Example

Consider the following static Java method.  

public class mult {

      static int jmult( int a, int b, int c )
    {
         return (a * a + b * b - c * c);
    }
}

It has been saved in the file, mult.java , and compiled into byte code in the class library, mult.class using the command   javac mult.java .

>    jmult := define_external(
     'jmult',
     CLASS="mult",
     CLASSPATH="C:/MyJavaRoutines.",
     JAVA,
     'a'::integer[4],
     'b'::integer[4],
     'c'::integer[4],     
     RETURN::integer[4]):

That's it, we're done.  The function,   jmult , can be used just like any other maple procedure now.

>    jmult(10, 3, 5);

84