MuPAD - Dynamic Modules [1]

Integration of Magnum in MuPAD

Andreas Sorgatz (andi@uni-paderborn.de) - 07. Nov. 1996

The package Magnum provides very fast factorization algorithms for univariate polynomials over a residue class ring Fp , where p is prime and less than 216. It has been (and still is) developed by Wolfgang Roth (roth@math.uni-mannheim.de). Magnum is available via anonymous ftp at:

ftp://obelix.statistik.uni-mannheim.de/public/magnum/magnum.tar.gz.

[About] -- [Demo] -- [Help Pages] -- [C++ Code] -- [Creation] -- [Availability]

About The Dynamic Module magnum

Magnum is integrated into MuPAD 1.3 with the dynamic module magnum [2]. So far, the following Magnum algorithms are accessible in MuPAD:

factor, gcd, irreducible, issqrfree, sqrfree
doc, id.

This module was tested on the following plattforms (further ports are planned).

PC/AT (Linux 2.0.7),
PC/AT (Solaris 2.5),
SunSPARC (Solaris 2.5).

A Demonstration Of The Factorization

Figure 1 demonstrates the speed of Magnum and the efficiency of dynamic MuPAD modules. After loading the magnum, a random polynomial is created and factorized by a Magnum function. The cpu time (ms) was measured under Linux 2.0 on a 90Mhz Pentium with 48Mb RAM.

Fig. 1: Using magnum in MuPAD

 >> module(magnum):
 >> P:= randpoly( [x], IntMod(65437), Degree=200, Terms=100 ):
 >> magnum::irreducible(P);
                              FALSE

 >> time( magnum::factor(P) );
                              31160

 >> magnum::doc():
 
 MODULE
     magnum - Factorization package for univariate polynomials over Fp
     [...]

The Online Help Pages

The following help pages are placed in a file magnum.mdh in the same directory as the module itself. They can be read during a MuPAD session via the function magnum::doc() - after the module magnum was loaded.

Fig. 2: The Online Help Pages

MODULE
    magnum - Factorization package for univariate polynomials over Fp

INTRODUCTION
    This module contains very fast algorithms  for the factorization of 
    univariate polynomials over residue class rings Fp, with p is prime
    and less than 2^16.  It interfaces the package  Magnum,  written by 
    Wolfgang Roth (roth@math.uni-mannheim.de). The file 'magnum.tar.gz' 
    (C++ code of Magnum) is originally available via anonymous ftp at:

           ftp://obelix.statistik.uni-mannheim.de/public/magnum

    The MuPAD source  of this interface and  a tested version of Magnum
    is available in  the contributions directory  of any official MuPAD 
    mirror site. The MuPAD home site is:

                ftp://math-www.uni-paderborn.de/MuPAD/

    For further technical information  refer to  the script 'magnum.sh'
    in the  MuPAD contributions directory  and to the documentation in-
    cluded in the Magnum package.

INTERFACE
    doc, factor, gcd, id, irreducible, issqrfree, sqrfree



NAME
    magnum::doc - Online documentation

SYNOPSIS
    magnum::doc()
    magnum::doc( func )

ARGUMENTS
    func - String, function name without the prefix "magnum::"

DESCRIPTION
    Displays a brief description of the module Magnum, respectively the
    function magnum::'func'. 

EXAMPLE:

    >> magnum::doc("factor");

    [...]

SEE ALSO
    module::help



NAME
    magnum::factor - Factorizes an univariate polynomial over IntMod(p)

SYNOPSIS
    magnum::factor( poly )

ARGUMENTS
    poly - An univariate polynomial over IntMod(p)

DESCRIPTION
    The function factorizes 'poly' over a residue class ring  IntMod(p) 
    with p is prime and p is less than 2^16. factor returns FAIL if the 
    input is invalid.

    factor returns the list  [u, f1, e1, ..., fn, en]  with  poly = u * 
    f1^e1 *...* fn^en, where fi is a irreducible factor  and 'u' is the 
    content of 'poly'. All fi are pairwise different and primitive.

EXAMPLE
    >> magnum::factor( poly(x^11+x+1,IntMod(6449)) );

                           2    3
    [1, poly(3211 x + 157 x  + x  + 150, [x], IntMod(6449)), 1,

                     2
    poly(- 1177 x + x  + 1815, [x], IntMod(6449)), 1,
 
                     2
    poly(- 1372 x + x  + 2487, [x], IntMod(6449)), 1,
 
              2
    poly(x + x  + 1, [x], IntMod(6449)), 1, 

    poly(x + 337, [x], IntMod(6449)), 1,
 
    poly(x + 2054, [x], IntMod(6449)), 1]
 
SEE ALSO
    magnum::irreducible, magnum::issqrfree, magnum::sqrfree, factor



NAME
    magnum::gcd - greatest common divisor of polynomials over IntMod(p)

SYNOPSIS
    magnum::gcd( [poly] ... )

ARGUMENTS
    poly - An univariate polynomial over IntMod(p)

DESCRIPTION
    gcd calculates the greatest common divisor of any number of polyno-
    mials over a residue class ring IntMod(p), with p is prime and p is 
    less than 2^16. gcd returns FAIL if the input is invalid.

EXAMPLE
    >> P:= poly(x^60*(-19) + x^384*(-202) + x^388*(-209), IntMod(503)):
       Q:= poly(x^20*146 + x^138*52 + x^425*172, IntMod(503)):
       magnum::gcd(P,Q);

             20
       poly(x  , [x], IntMod(503))

SEE ALSO
    magnum::irreducible, gcd



NAME
magnum::id - the identical function for polynomials over IntMod(p)

SYNOPSIS
    magnum::id( poly )

ARGUMENTS
    poly - An univariate polynomial over IntMod(p)

DESCRIPTION
    id converts a polynomial over a residue class ring IntMod(p),with p
    is prime and p is less than 2^16, into a Magnum polynomial and then
    back into a MuPAD polynomial.   This functions can be used to check
    the conversion routines.This is usefull when the magnum source code 
    was exchanged and a new dynamic MuPAD module was compiled

    In contrast to other  magnum module functions,  id returns detailed
    error messages when its input is invalid.

EXAMPLE
    >> P:= poly(x^20*146 + x^138*52 + x^425*172, IntMod(503)):
       magnum::id(P);

                 20       138        425
       poly(146 x   + 52 x    + 172 x   , [x], IntMod(503))

SEE ALSO
    id



NAME
    magnum::irreducible - tests if a polynomial over IntMod(p) is 
                          irreducible
SYNOPSIS
    magnum::irreducible( poly )

ARGUMENTS
    poly - An univariate polynomial over IntMod(p)

DESCRIPTION
    Tests if a polynomial  over a residue class ring  IntMod(p), with p 
    is prime and p is less than 2^16, is irreducible.  The function re-
    turns TRUE, respectively FALSE, or FAIL if the input was invalid.

EXAMPLE
    >> P:= poly(x^20*146 + x^138*52 + x^425*172, IntMod(503)):
       magnum::irreducible(P);

       FALSE

SEE ALSO
    magnum::issqefree, magnum::sqrfree, magnum::factor



NAME
    magnum::issqrfree - tests if a polynomial over IntMod(p) is
                        square free
SYNOPSIS
    magnum::issqrfree( poly )

ARGUMENTS
    poly - An univariate polynomial over IntMod(p)

DESCRIPTION
    Tests if the a polynomial over a residue class ring IntMod(p), with
    p is prime and p is less than 2^16, is square free.The function re-
    turns TRUE, respectively FALSE, or FAIL if the input was invalid.

EXAMPLE
    >> P:= poly(x^20*146 + x^138*52 + x^425*172, IntMod(503)):
       magnum::issqrfree(P);

       FALSE

SEE ALSO
    magnum::irreducible, magnum::sqrfree, magnum::factor



NAME
    magnum::sqrfree -  square-free factorization of polynomials over
                       IntMod(p)
SYNOPSIS
    magnum::sqrfree( poly )

ARGUMENTS
    poly - An univariate polynomial over IntMod(p)

DESCRIPTION
    sqrfree  calculates the  square-free  factorization of a polynomial
    'poly' over a residue class ring IntMod(p) with p is prime and p is 
    less than 2^16. sqrfree returns FAIL if the input is invalid.

    sqrfree returns the list  [u, f1, e1, ..., fn, en]  with poly = u * 
    f1^e1 * ...* fn^en,  where the fi  are the square-free factors of a 
    and 'u' is the content of 'poly'. The fi are primitive and pairwise 
    relatively prime.

EXAMPLE
    >> P:= poly(x^20*146 + x^138*52 + x^425*172, IntMod(503)):
       magnum::sqrfree(P);

       [172, poly(x, [x], IntMod(503)), 20

                118    405
       poly(12 x    + x    - 5, [x], IntMod(503)), 1]

SEE ALSO
    magnum::issqrfree, magnum::factor

The Source Code Of The Magnum Module Interface

The source code of the module interface only contains about 300 lines of C++ code - including comments. Figure 3 shows the complete source code.

Fig. 3: The Complete Source Code Of magnum

/******************************************************************************/
/* MODUL  : magnum.C - Module Interface for Magnum (refer to the README)      */
/* MuPAD  : Release 1.2.9a, 1.3                                               */
/* AUTHOR : Paul Zimmermann (Paul.Zimmermann@loria.fr)                        */
/*          Andreas Sorgatz (andi@uni-paderborn.de)                           */
/* CREATED: 26/09/96                                                          */
/* CHANGED: 07/11/96                                                          */
/*                                                                            */
/* This is a MuPAD interface to the package Magnum.  It is written in C++ and */
/* must be compiled into a dynamic MuPAD module by using the module generator */
/* mmg. For further information refer to the script 'magnum.sh'.              */
/*                                                                            */
/* Wolfgang Roth's (roth@math.uni-mannheim.de) package 'magnum' provides fast */
/* factorization algorithms  for polynomials over fields  Fp with p is prime. */
/* His package  'magnum.tar.gz'  is originally available via anonymous ftp at */
/*                                                                            */
/*           ftp://obelix.statistik.uni-mannheim.de/public/magnum             */
/*                                                                            */
/******************************************************************************/
MMG( info = "Module: Factorization of univariate polynomials over fields Fp" )

// Magnum header files /////////////////////////////////////////////////////////
//

#include "magnum/Prime.H"
#include "magnum/FpPolynom.H"
#include "magnum/FpPolynom_Set.H"


// Conversion routines for polynomials - Magnum <--> MuPAD /////////////////////
//

/******************************************************************************/
/* NAME:  Convert                                                             */
/******************************************************************************/
#define CONVERT(arg,magPoly,mupUndets,mupField,prime,expo,mode)               \
                                                                              \
  /* Check if 'arg' is a valid polynomial, convert it into its MuPAD list */  \
  /* representation and collect information for the further conversion.   */  \
                                                                              \
  MTcell  mupList, mupUndets, mupField;                                       \
  long    prime, expo;                                                        \
                                                                              \
  if( !mupPolyCheck(arg,mupList,mupUndets,mupField,prime,expo,mode) )         \
      MFreturn( MFcopy(MVfail) );                                             \
                                                                              \
  /* Create a Magnum polynomial with the collected information */             \
                                                                              \
  FpPolynom  magPoly( (Prime) prime );                                        \
                                                                              \
  mupPoly2mag( mupList, prime, magPoly );                                     \
  MFfree( mupList );                                                          

/******************************************************************************/
/* NAME:  mupPolyCheck                                                        */
/******************************************************************************/
static int mupPolyCheck ( MTcell      mupPoly,         // IN
                          MTcell     &mupList,         // OUT
                          MTcell     &mupUndets,       // OUT
                          MTcell     &mupField,        // OUT
                          long       &prime,           // OUT
                          long       &expo,            // OUT
                          int         ExitOnError=0    // IN
                        )
{
    int  error = 0;

    // Check if 'mupPoly' is an univariate polynomial over the finite field Fp
    // with p is prime and less than 2^16. Other polynomials cannot be handled
    // by Magnum.
    //
    if( !MFisPolynom(mupPoly) ) {
        if( ExitOnError ) MFerror( "Polynomial expected" );
        return( 0 );
    }
    mupUndets = MFop( mupPoly, 1 );
    if( MFnops(mupUndets) != 1 ) {
        if( ExitOnError ) MFerror( "Polynomial must be univariate" );
        return( 0 );
    }
    mupField = MFop( mupPoly, 2 );
    if( !MFisExpr(mupField,"IntMod") || MFnops(mupField) != 2 ) {
        if( ExitOnError ) MFerror( "Polynomial must be of type 'IntMod(p)'" );
        return( 0 );
    }
    MTcell  mprime = MFop(mupField,1);

    if( MFlt(mprime,MVzero) || MFgt(mprime,MFlong(65535)) ) {
        if( ExitOnError ) MFerror( "IntMod(p), p out of range" );
        return( 0 );
    }
    prime = MFlong( MFop(mupField,1) );
    expo  = 1;

    MTcell  result = MFcall( "isprime", 1, MFlong(prime) );
    if( !MFisTrue(result) ) {
        MFfree( result );
        if( ExitOnError ) MFerror( "IntMod(p), p must be prime" );
        return( 0 );
    }
    MFfree( result );

    // Convert the MuPAD polynomial into its list representation, which is much
    // easier to analyse during the further conversion into a Magnum polynomial.
    //
    mupList = MFcall( "poly2list", 1, MFcopy(mupPoly) );
    
    return( 1 );
}


/******************************************************************************/
/* NAME:  mupPoly2mag                                                         */
/******************************************************************************/
static int mupPoly2mag ( MTcell      mupList,         // IN
                         long        prime,           // IN
                         FpPolynom  &magPoly          // OUT
                       )
{
    // Convert the list representation of a MuPAD polynomial into a Magnum
    // polynomial. Use 'prime' for this.
    //
    MTcell     monom;
    long       coeff, expo, length = MFnops(mupList);

    for( int pos = 0; pos < length ; pos++ ) {
        monom = MFgetList( &mupList, pos );
        coeff = MFlong( MFgetList(&monom,0) );
        if( coeff < 0 ) coeff += prime;
        expo  = MFlong( MFgetList(&monom,1) );
        magPoly += FpPolynom( magPoly.descriptor, (Fp)coeff, expo );
    }
    return( 1 );
}

/******************************************************************************/
/* NAME:  magPoly2mup                                                         */
/******************************************************************************/
static MTcell magPoly2mup ( const FpPolynom  &magPoly,         // IN
                                  MTcell     &mupUndets,       // IN
                                  MTcell     &mupField         // IN
                          )
{
    MTcell  mupList, mupPoly, monom;
    long    pos = 0;

    // First create a list representation of the MuPAD polynomial. Then
    // convert is into a native polynomial by using 'poly'.
    //
    mupList = MFnewList( magPoly.length() );

    for( FpPolynom_Iterator x_iter(magPoly); x_iter(); ++x_iter ) {
        monom = MFnewList( 2 );
        MFsetList( &monom, 0, MFlong((long)x_iter()->factor) );
        MFsetList( &monom, 1, MFlong((long)x_iter()->power)  );
        MFsetList( &mupList, pos++, monom );
    }
    return( MFcall("poly", 3, mupList, MFcopy(mupUndets), MFcopy(mupField)) );
}

/******************************************************************************/
/* NAME:  magPolyListLen                                                      */
/******************************************************************************/
static long magPolyListLen ( const FpPolynom_List &magPolyList )
{
    long  n = 0;

    // How many polynomials are in this list ?
    //
    for( FpPolynom_List_Iterator l_iter(magPolyList); l_iter(); ++l_iter ) {
        n += l_iter()->set().size();
    }
    return( n );
}

/******************************************************************************/
/* NAME:  magPolyList2mup                                                     */
/******************************************************************************/
static MTcell magPolyList2mup ( const FpPolynom_List  &magPolyList,     // IN
                                      MTcell          &mupUndets,       // IN
                                      MTcell          &mupField         // IN
                              )
{
    FpPolynom_List_Iterator  l_iter( magPolyList );
    MTcell                   mupList, mupPoly;
    long                     pos = 1;

    // Create a MuPAD list with the first element is the integer factor.
    //
    mupList  = MFnewList( magPolyListLen(magPolyList)*2+1 );
    MFsetList( &mupList, 0, MFlong((long) magPolyList.factor) );

    // Insert pairs (poly,exponent) into the factor list.
    //
    if( l_iter() ) do {
        FpPolynom_Set_Iterator  s_iter( l_iter()->set() );
        if( s_iter() ) do {
            mupPoly = magPoly2mup( s_iter()->polynom(), mupUndets, mupField );
            MFsetList( &mupList, pos++, mupPoly );
            MFsetList( &mupList, pos++, MFlong((long)l_iter()->power) );
        } while( (++s_iter)() );
    } while( (++l_iter)() );
    MFsig ( mupList );
    return( mupList );
}


// MuPAD interface functions - these are visible in MuPAD //////////////////////
//

/******************************************************************************/
/* NAME:  magnum::id - identity, check conversion routines                    */
/******************************************************************************/
MFUNC( id, MCnop )
{
    MFnargsCheck(1);

    CONVERT( MFarg(1), magPoly, mupUndets, mupField, prime, expo, 1 );

    MFreturn( magPoly2mup( magPoly, mupUndets, mupField ) );
} MFEND


/******************************************************************************/
/* NAME:  magnum::factor - factorizes a polynomial and returns a factor list  */
/******************************************************************************/
MFUNC( factor, MCnop )
{
    MFnargsCheck(1);

    CONVERT( MFarg(1), magPoly, mupUndets, mupField, prime, expo, 0 );

    FpPolynom_List  magPolyList;

    factorize( magPolyList, magPoly );

    MFreturn( magPolyList2mup( magPolyList, mupUndets, mupField ) );
} MFEND


/******************************************************************************/
/* NAME:  magnum::gcd - returns the greatest common divisor of polynomials    */
/******************************************************************************/
MFUNC( gcd, MCnop )
{
    if( MVnargs == 0 )
        MFreturn( MFcopy(MVzero) );
    if( MVnargs == 1 )
        MFreturn( MFcopy(MFarg(1)) );

    CONVERT( MFarg(1), magPoly, mupUndets, mupField, prime, expo, 0 );

    for( long i = 2; i <= MVnargs; i++ ) {

        CONVERT( MFarg(i), magPoly2, mupUndets2, mupField2, prime2, expo2, 0 );

        if( prime != prime2 || !MFequal(mupUndets,mupUndets2) ) {
            MFreturn( MFcopy(MVfail) );
        }
        if( magPoly == magPoly2 )
            continue;
        magPoly = gcd( magPoly, magPoly2 );
    }

    MFreturn( magPoly2mup( magPoly, mupUndets, mupField ) );
} MFEND


/******************************************************************************/
/* NAME:  magnum::irreducible - check if a polynomial is irreducible          */
/******************************************************************************/
MFUNC( irreducible, MCnop )
{
    MFnargsCheck(1);

    CONVERT( MFarg(1), magPoly, mupUndets, mupField, prime, expo, 0 );

    if( magPoly.is_irreducible() ) { MFreturn( MFcopy(MVtrue ) ); }
    else                           { MFreturn( MFcopy(MVfalse) ); }
} MFEND


/******************************************************************************/
/* NAME:  magnum::issqrfree - check if a polynomial is squarefree             */
/******************************************************************************/
MFUNC( issqrfree, MCnop )
{
    MFnargsCheck(1);

    CONVERT( MFarg(1), magPoly, mupUndets, mupField, prime, expo, 0 );

    if( magPoly.is_squarefree() ) { MFreturn( MFcopy(MVtrue ) ); }
    else                          { MFreturn( MFcopy(MVfalse) ); }
} MFEND


/******************************************************************************/
/* NAME:  magnum::sqrfree - returns a list of squarefree factors of a poly.   */
/******************************************************************************/
MFUNC( sqrfree, MCnop )
{
    MFnargsCheck(1);

    CONVERT( MFarg(1), magPoly, mupUndets, mupField, prime, expo, 0 );

    FpPolynom_List  magPolyList;

    squarefree( magPolyList, magPoly );

    MFreturn( magPolyList2mup( magPolyList, mupUndets, mupField ) );
} MFEND

How To Create The Executable Module

In the following example it is suppused that the Magnum library libmagnum.a has already been build and that all Magnum header files have to be available. The module interface source code has been stored in the file magnum.C. With this, the MuPAD module generator is called to create the dynamic module (refer to figure 4). The result is the binary file magnum.mdm, which is placed in the current directory and can be used by MuPAD instantly.

Fig. 4: Creating The Dynamic Module magnum

andi> mmg -v -I$MAGINC -L$MAGLIB -lmagnum -lm magnum.C

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

g++ -fpic -c MMGmagnum.C -o magnum.o 
    -DPARI_C_PLUSPLUS -DLONG_IS_32BIT -DPOINTER_IS_32BIT -I. -Iinclude 
    -I/wiwianka/user/andi/MuPAD/SOURCE/DEV/share/mmg/include/kernel 
    -I/wiwianka/user/andi/MuPAD/SOURCE/DEV/share/mmg/include/pari 
    -I/wiwianka/user/andi/MuPAD/SOURCE/DEV/share/mmg/include/mmt

Mesg.: Linking dynamic module ...

g++ -G -o magnum.mdm magnum.o -L. -Llibrary -lmagnum -lm 
    -L/wiwianka/user/andi/MuPAD/SOURCE/DEV/i386/lib

Mesg.: Ok

Appendix

Binary modules as well as the module source code and a shell script for the automatic creation will be available for the MuPAD release 1.3.0. 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] Using the NAGC Library in MuPAD
[5] How to create MuPAD scanners with (f)lex


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