Product Tips & Techniques

Tips and Tricks on how to get the most about Maple and MapleSim

I've had a few request to provide some more information on External Calling, so I thought I would make a few posts about it. This first post will be a high level description of External Calling and how it works, with examples coming later. As External Calling is an advanced topic, I am going to assume you know how to compile a shared library and are generally familiar with the C language. Although this first post won't require any real programming knowledge.

What is External Calling?

External Calling is the name for Maple's ability to connect to and call functions from other programming languages. Maple uses this for various reasons. We have written our own libraries in C, C++ and Java to solve particular problems. We partner with various labs around the world who have developed code, often in languages like C or C++, so external calling is used to interface with their code. We also connect to high performance libraries like NAG and BLAS to provide those high performance routines in Maple. Of course, you can use External Calling to connect Maple to your code as well.

Although Maple can call various programming languages, the most common languages we connect to are C and C++, and those are the languages I am going to focus on.

How does it work?

In Maple, you call ?define_external or use the ?ExternalCalling package. Both these methods take a description of the function that you want to call and returns a Maple procedure. Normally you would assign the procedure to a name and then call the externally defined function just like any other Maple procedure.

There are a couple different ways to use define_external to connect to a shared library, the differences are mostly concerned with how the parameters given in Maple are converted to parameters used in the external function.

  • Wrapperless external calling. With wrapperless external calling, Maple calls a function implemented in the shared library by automatically converting the values given in Maple into valid types for the external function.
  • Generated wrappers: With generated wrappers, Maple automatically generates a small C library that handles conversions from Maple values to the values used in the external function. Using generated wrappers allows Maple to handle more data types, like call back procedures.
  • Custom wrappers: A custom wrapper is a C function that you write yourself. This function accepts arguments as Maple data structures and returns a Maple data structure. You are responsible for converting the Maple data structures into whatever forms you need and converting your computed value back into a Maple data structure. Maple provides the External Calling API to assist in working with Maple from the externally defined function.

The first two forms of external calling are the easiest to do, however they are also the most limited. Internally we exclusively (I think) use the third, custom wrapper, form of external calling. That is the form I am going to talk about.

Custom Wrapper

The name "custom wrapper" is a bit of a misnomer. The function that you write does not need to "wrap" anything, it can implement anything you want. As long as you can convert the result into a Maple data structure, you can pass it back into Maple. In fact Maple also supports returning generic data, via the ?MaplePointer routines, but that is a more complex topic for a later blog post.

Your external function is simply a C function with the following calling convention:

ALGEB CustomWrapper( MKernelVector kv, ALGEB args )

ALGEB is the C data type that represents a Maple data structure. The MKernelVector is a data structure that acts as an intermediary between your external calling routines and the Maple engine. You will need to pass this structure back into the External Calling API functions. Both of these types, plus the External Calling API functions are defined in a header, maplec.h, that needs to be included in your code. I will provide more details when I provide examples.

The External Calling API

The External Calling API is a set of functions that we make available for working with the Maple Engine from external code. Maple also allows third party applications to load the Maple engine as a shared library, we call this ?OpenMaple. The External Calling functions are also available in OpenMaple, so you will often see OpenMaple used in the Maple help pages. Most functions can be used in both OpenMaple and External Calling, except for a few that are OpenMaple specific and involve starting and stopping the Maple Engine.

Maple's help system documents all the External Calling functions so you can see what is available. There is an overview of the external calling functions on this page, ?ExternalCalling,C,API. Briefly, however there are functions for converting Maple types to C and back, creating and interacting with Maple data structures (list, set, rtable, table, string, etc), creating and interacting with Maple language elements (names, procedures, etc), printing to the Maple interface, memory allocation, evaluating Maple statements and raising exceptions. There is even a C interface to the Task Programming Model.

Next Time...

In my next post I will provide some examples of using the External Calling API to actually do stuff in an externally defined procedure.  However, I am going to spend some time trying to figure out the easiest way for you to get the tools you'll need to be able to develop externally defined functions yourself, so my next post might take a bit of time.

Darin

I have always preferred the notation  for the derivative of

When mucking around with my Maple setup, I occasionally find it useful to check various kernelopts settings.  To simplify this task, I wrote the simple kerneloptsall procedure, which prints all the (useful) values of kernelopts:

(**) kerneloptsall();
ASSERT                    = false
assertlevel               = 0

Using the Open Maple application program interface (API), the ExternalCalling module, a C compiler, and some basic understanding of the Maple data structure format, you can create Maple utilities that run nearly as fast as Maple builtin procedures.

To show how this is done, I will start with a simple example and then proceed to a slightly more complex procedure that improves ?ListTools[SearchAll]

@Alejandro Jakubi Alejandro this is something like the 3rd time in as many weeks that you have used applyrule to nice effect, deftly providing a more general solution.

This is great because applyrule deserves more notice, if not as a bug-free command then certainly as representative of a symbolic problem-solving methodology. (And heavier use can lead to more bug...

(This is a reply to PatrickT, who asked about a certain ArrayTools:-Copy example.)

Suppose that you need to do a computation which requires, in part, a certain subportion of a Vector V. Let's call the routine which does the work as `f`. Let's suppose that `f` is a system command and not something that we write ourselves. One natural way to call `f` and supply the subvector is to call `f` like so:

   f( V[a..b] );

Here the inner range a..b denotes...

@John Fredsted

This thread is 3 years old, I don't wish to upset anyone by "reviving" it, forgive me.

I came to this thread as I was searching for information on how to write efficient procedures.

I learned a great deal by looking at how others write a proc.

Now the LinearAlgebra package implements a KroneckerProduct so the need for user-written procedures to...

A new release of MapleSim is now available.

MapleSim 4.5 Highlights

  • Enhanced Modelica support, including the ability to access new collections of components using the Modelica import feature

  • Increased speed and modeling capabilities for continuous systems with discrete events. The enhanced engine handles a far greater class of these systems than earlier versions, and shows significant...

Maple 14.01 is now available. It provides updates in many areas, including:

  • Mathematics: Updates to the VectorCalculus, DifferentialAlgebra, MathematicalFunctions, and Student packages, the convert command, and tools for solving differential equations
  • Interface: Enhancements to context menus, tables, embedded components, document blocks, and the start-up code region
  • Plotting:

A couple of days ago I found out that gzread from the zlib library can be used for fast reading of binary files in Maple from the disk to memory - about 100 times faster than readbytes - something like in the following simplified example, 

A:=Array(1..2^26,99,datatype=integer[1]):

time(writebytes("A",A));close("A");

                                9.360

B:=Array(1..2^26,1,datatype=integer[1]):
time(readbytes("A",B));close("A");

                                8.065
B[1],B[-1];

                                99, 99

myreadbytes:=proc(f)
local gzopen, gzread, gzclose, n, p, A;
gzopen:=define_external('gzopen',
    'path'::string,
    'mode'::string,
    'RETURN'::integer[4],
    'LIB'="zlibwapi.dll");
gzread:=define_external('gzread',
    'file'::integer[4],
    'buf'::REF(ARRAY(datatype=integer[1])),    
    'len'::integer[4],
    'RETURN'::integer[4],
    'LIB'="zlibwapi.dll");
gzclose:=define_external('gzclose',
    'file'::integer[4],
    'RETURN'::integer[4],
    'LIB'="zlibwapi.dll");
n:=FileTools:-Size(f);
A:=Array(1..n,datatype=integer[1]);
try p:=gzopen(f,"rb");
if gzread(p,A,n)=n
then return A end if
finally gzclose(p)
end try
end proc:
time(assign(C=myreadbytes("A")));

                                0.062

C[1],C[-1];

                                99, 99

'time(myreadbytes("A"))'$5;


                  0.078, 0.062, 0.046, 0.046, 0.046

E:=Array(1..2^26,2,datatype=integer[1]):
time(ArrayTools:-Copy(A,E));

                                0.093

That needs some tweaking, because that works only on uncompressed files. If a file ("A" in this example) was gzipped, then the gzread would ungzip n (uncompressed) bytes in it in this example, instead of copying it into the memory - but it is not a big deal, in general.

Does anybody know about a similar replacement for writebytes? gzwrite doesn't work for copying (it compresses the array.)

I used the zlibwapi.dll library from http://www.winimage.com/zLibDll/index.html, it is a version of zlib 1.2.5 (written by Jean-Loup Gailly and Mark Adler) built by Gilles Vollant. The code is for a 32-bit system (Windows). That should work in 32-bit Linux after replacing that dll with standard libz.so.1, as well as on 64-bit systems after replacing integer[4] with integer[8] in most places.

Student's t distribution is named after William Sealy Gosset's pseudonym, Student. He published using this pseudonym because his employer, the Guinness brewery in Ireland, did not allow its employees to publish scientific papers after an incident where trade secrets were disclosed. In this blog...

This post is a further development of my earlier question in reply to John's post. I have implemented a basic version of the CANDECOMP/PARAFAC algorithm referred to on Wikipedia and described 

There are a few ways to view the source of a Maple procedure, such as by using the commands  showstat and print. And these work as usual for the exports of a module. But for procedures which are declared as local to a module these methods do not work right away since by default modules' contents are opaque.

One way around this is to change a setting, by issuing kernelopts(opaquemodules=false) prior to attempting...

I selected the whole document and expanded the document blocks. There near the top of the document were nine copies of "plots[interactive]()" all in a row. Deleting them fixed the problem. Seldom is a fix so easy. Many thanks.

If you want to know what ::uneval does (it's an advanced option for procedure parameters), you can look at the uneval section of ?parameter_modifiers.  It is useful when you want to write a function which works on raw user input rather than on evaluated input.  This is quite tricky, and fraught with danger, and should only be used as a last resort;  but sometimes it really is rather handy.

First 33 34 35 36 37 38 39 Last Page 35 of 66