MuPAD - Dynamic Modules [1]

Dragon cures

Andreas Sorgatz (andi@uni-paderborn.de) - 01. Dec. 1996

The module dragon is just a game play. It allows to create large dragon curves in the form of a polygon, which can be printed by the MuPAD graphics tool vcam.
[About] -- [Demo] -- [Source] -- [Creation] -- [Availability]

About Dragon Curves

Let n be a positive integer. A dragon curve Dn is sequence of elements {0, 1} with: D0 := 1 and Dn := Dn-11complement(reverse(Dn-1)). Ergo D1 := 110, D2 := 1101100 and so on. You need exponential time and memory to create a dragon curve.

To display a dragon draw with a pen and with constant speed a straight line on a paper, while interpreting the dragon sequence. Reading the value 1, turn left (90 degree) and reading the value 0, turn right (-90 degree). You will get some nice fractal images.

The module dragon runs on all UNIX plattforms on which MuPAD supports dynamic modules.

A Demo of Dragon curves

Figure 1 demonstrates how to load and use the module dragon. The first image is displayed as created by the module. The other images are manipulated interactively with the MuPAD graphics tool vcam in order to look nicer. You can click on the images to expand them.

Fig. 1: Playing With The Module Dragon

 >> module(dragon):                          # load the dragon module   #
 >> dragon(0);                               # display the polynomial   #

polygon(point(0, 0, 0), point(0, 0, 1), point(1, 0, 1))
plot3d( [Mode=List, [dragon(4)]] ): # display the dragon image #

plot3d( [Mode=List, [dragon(12)]] ):

plot3d( [Mode=List, [dragon(14)]] ):

Be carefull when creating larger dragon curves. You need a lot of memory!

The Source Code

Figure 2 shows the complete source code of the module dragon.

Fig. 2: The Source Code Of The Module dragon

/******************************************************************************/
/* FILE:  dragon.C                                                            */
/******************************************************************************/
#define NORTH   0
#define EAST    1
#define SOUTH   2
#define WEST    3

/******************************************************************************/
/* NAME:        new                                                           */
/******************************************************************************/
MFUNC( new, MCnop ) 
{
    MFnargsCheck(1);
    MFargCheck(1,DOM_INT);
    
    long  n = MFlong(MFarg(1));                       // Number of iterations

    if( n < 0 || n > 31 )                           
        MFerror( "Integer out of range [0..31]" );

    long   length = (2L << n) -1L;                    // Create a byte vector
    char*  dragon = (char*) MMMEmalloc( length );

    dragon[0] = 1;                                    // Create the dragon
    for( long len = 1; n--; len = 2*len+1 ) {
        dragon[len] = 1;
        for( long i = 1; i <= len; i++ ) 
            dragon[len+i] = ( dragon[len-i] ? 0:1 );
    }

    long     posx = 0, posy = 0;                      // Convert into a polygon
    MTcell   tmp1, tmp2;
    MTcell   pol = MFnewPolygon( length+2 );
    MTcell*  pnt = MFopAdr(pol, 0);
    MFpoolInsert( &pnt );

    *pnt++ = MFnewPoint( tmp1=MFlong(posx), MVzero, tmp2=MFlong(  posy) );
    MFfree(tmp1); 
    MFfree(tmp2);
    *pnt++ = MFnewPoint( tmp1=MFlong(posx), MVzero, tmp2=MFlong(++posy) );
    MFfree(tmp1); 
    MFfree(tmp2);

    for( int i=0, go=NORTH; i < length; i++ ) {
        switch( go ) {
         case NORTH: if( dragon[i] ) posx++; else posx--; break;
         case EAST : if( dragon[i] ) posy--; else posy++; break;
         case SOUTH: if( dragon[i] ) posx--; else posx++; break;
         case WEST : if( dragon[i] ) posy++; else posy--; break;
         default   : MFerror( "Fatal error" );
        }
        go = (go + (dragon[i] ? 1:3)) % 4;
        
        *pnt++ = MFnewPoint( tmp1=MFlong(posx), MVzero, tmp2=MFlong(posy) );
        MFfree(tmp1); 
        MFfree(tmp2);
    }
    MMMEfree( dragon );
    
    MFpoolDelete(&pnt);
    MFinactive  (&pol);
    MFsig(pol);
    MFreturn(pol);
} MFEND

The Creation Of The Module

You just need to start the module generator with the argument 'dargon.C'. Refer to figure 3.

Fig. 3: Creating The Module dragon

andi> mmg -v dragon.C

MMG -- MuPAD-Module-Generator -- V-1.3.0  Oct.96
Mesg.: Scanning source file ... 
Mesg.: 1 function(s) and 0 option(s) found in 66 lines
Mesg.: Creating  extended module code ... 
Mesg.: Compiling extended module code ... 

g++ -fpic  -c MMGdragon.C -o dragon.o 
    -DPARI_C_PLUSPLUS -DLONG_IS_32BIT -DPOINTER_IS_32BIT 
    -I/home/andi/MuPAD/DEV/share/mmg/include/kernel 
    -I/home/andi/MuPAD/DEV/share/mmg/include/pari 
    -I/home/andi/MuPAD/DEV/share/mmg/include/mmt 

Mesg.: Linking dynamic module ... 

ld -shared -o dragon.mdm dragon.o -L/home/andi/MuPAD/DEV/i386/lib 

Mesg.: Ok

Appendix

The module dragon is available since MuPAD release 1.2.9a. Please refer to the contrib directory of any official MuPAD ftp site.

Bibliography

[1] Dynamische Module, A. Sorgatz, MuPAD Reports, Teubner Verlag, Stuttgart, Oktober 1996. http://math-www.uni-paderborn.de/MuPAD/BIB/sorgatz96.html
[2] A first integration of the factorization function of Magnum in MuPAD 1.2.9a was done by Paul Zimmermann: http://www.loria.fr/~zimmerma/mupad/magnum.html.
[3] Spiel (fast) ohne Grenzen, A. Sorgatz, Linux Magazin, Ausgabe 01/97.
[4] Integration of Magnum in MuPAD
[5] Using the NAGC Library in MuPAD
[6] How to create MuPAD scanners with (f)lex


Author: Andreas Sorgatz (andi@uni-paderborn.de)
Last update: 01. Dec. 1996