iconEuler Home

Compiled Code in Euler

This is a short introduction into compiled C code in Euler. Compiled
code is usually much faster than Euler code, and can be imported from
other sources more easily.

Euler can load DLL (dynamic link library) files, and call the
functions exported in these libraries. These libraries must be Windows
DLLs from any compiler that can bind to a library. To make it easy,
Euler comes with tccompile a Tiny C Compiler. See the documentation
about more details on this compiler.

Here is a first benchmark. The recursive version of fib computes the
Fibonacci numbers in a very inefficient way. But it is good to measure
the overhead of calling a function.

The following compiler call will not work, unless you have write
access to the current directory. For the introduction notebook, this
usually not the case. You have to copy the notebook and the fib.c file
into a directory with write access (see below).
>// tccompile fib
The code for fib in fib.c is the following:

double hfib (int n)
{
  if (n<2) return n;
  return hfib(n-1)+hfib(n-2);
}

There are more functions for the communication with Euler. But we
cover those later.

We load the DLL with the following command. The parameters are:
DLL-name, function-name, number-of-parameters.
>dll("fib","fib",1);
The running time is 1/20 second.
>tic; fib(30), toc;
832040

Used 0.047 seconds
Here is the same function in Euler.
>function efib(n) ...
  if n<2 then return n; endif;
  return efib(n-1)+efib(n-2);
endfunction
The running time is much worse (15 seconds on my computer).
>tic; efib(30), toc;
832040

Used 14.664 seconds
By the way, I checked it on Matlab, and it was even longer (24
seconds).

It should be noted, that the iterative version is much better, even if
we use the utility function sequence.
>tic; sequence("x[n-1]+x[n-2]",[1,1],30), toc;
[ 1  1  2  3  5  8  13  21  34  55  89  144  233  377  610  987  1597
2584  4181  6765  10946  17711  28657  46368  75025  121393  196418
317811  514229  832040 ]

Used 0.031 seconds
We should explain the functions in the DLL which handle the
communication with Euler. The complete content of fib.c is the
following.
>printfile("fib.c");
#include "dlldef.h"
#include <stdio.h>

double hfib (int n)
{
    if (n<2) return n;
    return hfib(n-1)+hfib(n-2);
}

EXPORT char * fib (header *hd[], int np, char *ramstart, char *ramend)
{
    start(ramstart,ramend); // required !!!

    int n=getint(hd[0]);
    IFERROR("Need an integer");
    
    new_real(hfib(n));
    
    return newram;
}

EXPORT char * fibv (header *hd[], int np, char *ramstart, char *ramend)
{
    start(ramstart,ramend); // required !!!

    int n=getint(hd[0]);
    IFERROR("Need an integer");
    CHECK(n>1,"Need an interger >1");
    
    header *res=new_matrix(1,n+1);
    double *m=matrixof(res);
    m[0]=0; m[1]=1;
    int i;
    for (i=2; i<=n; i++) m[i]=m[i-1]+m[i-2];
    
    return newram;
}

As you see, the exported functions get an array of Euler headers, the
number of parameters, and two pointers to the current start of the
Euler stack and its end.

Euler calls two other functions in the DLL, which are exported in the
dlldef.c file. Have a look at the documenation for more information.

See: ../documentation/compile

There are some more useful examples of C code on the following pages.

See: Examples/Mandelbrot
See: Examples/Distribution of Primes

Compiling and Editing

If you develop your own DLLs, you need to unload the DLL before you
compile a new version.
>closedll("fib");
If you want to test the following compiler, press F10 on the command
line. This will open the external editor with fib.c loaded. Save the
file to your desktop. Then save this notebook to the desktop, close it
and open it again.
>tccompile fib;
Most likely you want to put the following line to an Euler file. Then
the user can simply load the Euler file with

load fib

and run all DLL commands.
>dll("fib","fib",1);
You can also provide pseudo functions, which only serve as a comment
line.
>function comment fib (n:integer) ...
## compute the n-th Fibonacci number recursively
endfunction
The user will now get help, and also find the function in the status
line.
>help fib
fib is an Euler function.

function fib (n: integer)

 Entered from command line. 
 compute the n-th Fibonacci number recursively


Search Maxima for help:

fib (<n>)

For more information try: mxmhelp fib

Efficient Version

For a test, we add a more efficient version of fib.
>closedll("fib"); tccompile fib; dll("fib","fibv",1);
The function now looks like this.

EXPORT char * fibv (header *hd[], int np, char *ramstart, char
*ramend)
{
  start(ramstart,ramend); // required !!!
  
  int n=getint(hd[0]);
  IFERROR("Need an integer");
  CHECK(n>1,"Need an interger >1");
  
  header *res=new_matrix(1,n+1);
  double *m=matrixof(res);
  
  m[0]=0; m[1]=1;
  int i;
  for (i=2; i<=n; i++) m[i]=m[i-1]+m[i-2];
  
  return newram;
}

We generate a matrix on the stack, and fill it with the Fibonacci
numbers.

The running time cannot be measured in seconds.
>tic; v=fibv(30); toc;
Used -2.90878e-014 seconds

Euler Home