Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it

563553 views
//// Singular library normaliz.lib

version="version normaliz.lib 4.0.2.0 Sept_2015 "; // $Id: c95d3329501ff768a1a262abad95a50b4b4f5452 $
category="Commutative Algebra";
info="
LIBRARY: normaliz.lib  Provides an interface for the use of Normaliz 2.11 or
         newer within SINGULAR.
AUTHORS: Winfried Bruns, [email protected]
         Christof Soeger, [email protected]

OVERVIEW:
@texinfo
The library normaliz.lib provides an interface for the use of Normaliz 2.11 or
newer within SINGULAR. The exchange of data is via files.
In addition to the top level
functions that aim at objects of type ideal or ring, several other auxiliary
functions allow the user to apply Normaliz to data of type intmat. Therefore
SINGULAR can be used as a comfortable environment for the work with Normaliz.
@* Please see the @code{Normaliz.pdf} (included in the Normaliz
distribution) for a more extensive documentation of Normaliz.

Normaliz allows the use of a grading. In the Singular functions that access
Normaliz the parameter grading is an intvec that assigns a (not necessarily
positive) degree to every variable of the ambient polynomial ring.
But it must give positive degrees to the generators given to function.

Singular and Normaliz exchange data via files. These files are automatically
created and erased behind the scenes. As long as one wants to use only the
ring-theoretic functions there is no need for file management.
@*Note that the numerical invariants computed by Normaliz can be
accessed in this \"automatic file mode\".
@*However, if Singular is used as a frontend for Normaliz or the user
wants to inspect data not automatically returned to Singular, then
an explicit filename and a path can be specified for the exchange of
data. Moreover, the library provides functions for access to these files.
Deletion of the files is left to the user.

Use of this library requires the program Normaliz to be installed.
You can download it from
@uref{http://www.mathematik.uni-osnabrueck.de/normaliz/}. Please make sure
that the executables are in the search path or use setNmzExecPath
(@ref{setNmzExecPath}).
@end texinfo

KEYWORDS: integral closure; normalization; toric ring

PROCEDURES:
 intclToricRing(ideal I)      computes the integral closure of the toric ring
                              generated by the leading monomials of the
                              elements of I in the basering
 normalToricRing(ideal I)     computes the normalization of the toric ring
                              generated by the leading monomials of the
                              elements of I
 normalToricRingFromBinomials(ideal I)  computes the normalization of the
                              polynomial ring modulo the unique minimal binomial
                              prime ideal of the binomial ideal I
 ehrhartRing(ideal I)         considers the exponent vectors of the elements of I
                              as points of a lattice polytope and computes the
                              integral cloure of the polytopal algebra
 intclMonIdeal(ideal I)       Computes the integral closure of the Rees algebra
                              of the ideal generated by the leading monomials of
                              the elements of I
 torusInvariants(intmat T)    computes the ring of invariants of a torus action
 finiteDiagInvariants(intmat C)  computes the ring of invariants of a finite
                                 abelian group acting diagonally on a polynomial
                                 ring
 diagInvariants(intmat C)     computes the ring of invariants of a
                              diagonalizable group
 intersectionValRings(intmat V)   computes the intersection of the polynomial
                                  ring with the valuation rings of monomial
                                  valuations
 intersectionValRingIdeals(intmat V)       computes ideals of monomial valuations

 showNuminvs()                prints the numerical invariants found by Normaliz
 exportNuminvs()              exports the numerical invariants found by Normaliz

 setNmzOption(string s, int onoff) sets the option s to onoff
 showNmzOptions()             prints the enabled options to the standard output

 normaliz(intmat sgr,int nmz_mode) applies Normaliz
 setNmzExecPath(string nmz_exec_path_name) sets the path to the Normaliz
                                           executable

 writeNmzData(intmat sgr, int n_mode) creates an input file for Normaliz
 readNmzData(string nmz_suffix) reads the Normaliz output file with the
                                specified suffix

 setNmzFilename(string nmz_filename_name) sets the filename for the exchange
                                          of data
 setNmzDataPath(string nmz_data_path_name) sets the directory for the exchange
                                           of data
 writeNmzPaths()              writes the path names into two files
 startNmz()                   retrieves the path names written by writeNmzPaths
 rmNmzFiles()                 removes the files created for and by Normaliz

 mons2intmat(ideal I)         returns the intmat whose rows represent the
                              leading exponents of the elements of I
 intmat2mons(intmat expo_vecs) returns the ideal generated by the monomials
                               which have the rows of expo_vecs as
                               exponent vector
 binomials2intmat(ideal I)    returns the intmat whose rows represent the
                              exponents of the elements of the binomial ideal I
";


// helpers

static proc desInt(string intname, int value)
// define, export and set an integer
{
    int exists;
    if(defined(`intname`)){exists=1;}
    if(!exists)
    {
        int `intname`=value;export(`intname`);
    }
    `intname`=value;
}

static proc desString(string stringname, string value)
// define, export and set a string
{
    int exists;
    if(defined(`stringname`)){exists=1;}
    if(!exists)
    {
        string `stringname`=value;export(`stringname`);
    }
    `stringname`=value;
}

static proc queryInt(string intname)
// if intname is defined, return(intname), else return(0)
{
    int exists,value;
    if(defined(`intname`)){exists=1;}
    if(!exists)
    {
        return(0);
    }
    return(`intname`);
}

static proc queryString(string stringname)
// if stringname is defined, return(stringname), else return("")
{
    int exists;
    string value;
    if(defined(`stringname`)){exists=1;}
    if(!exists)
    {
        return("");
    }
    return(`stringname`);
}

static proc fileExists(string f)
{
    return(status (f,"exists")=="yes");
}

static proc appendSlash(string s)
// if nonempty and / is not the terminating char
{
    if(size(s)>0)
    {
        if(s[size(s)]!="/")
        {
            s=s+"/";
            return(s);
        }
    }
    return(s);
}

// filenames and paths

proc setNmzExecPath(string nmz_exec_path_name)
"USAGE:   setNmzExecPath(string s);   @code{s} path to the Normaliz executable
CREATE:   @code{Normaliz::nmz_exec_path} to save the given path @code{s}
NOTE:     It is not necessary to use this function if the Normaliz executable
          is in the search path of the system.
SEE ALSO: setNmzOption
EXAMPLE:  example setNmzExecPath; shows an example"
{
    desString("nmz_exec_path",nmz_exec_path_name);
    nmz_exec_path=appendSlash(nmz_exec_path);
}
example
{ "EXAMPLE:";echo = 2;
  setNmzExecPath("../Normaliz/");
}

proc setNmzFilename(string nmz_filename_name)
"USAGE:   setNmzFilename(string s);
CREATE:   @code{Normaliz::nmz_filename} to save the given filename @code{s}
NOTE:     The function sets the filename for the exchange of data. Unless a
          path is set by setNmzDataPath, files will be created in the current
          directory.
          @* If a non-empty filename is set, the files created for and by
             Normaliz are kept. This is mandatory for the data access functions
             (see @ref{writeNmzData} and @ref{readNmzData}).
          @* Resetting the filename by setNmzFilename(\"\") forces the library
             to return to deletion of temporary files, but the files created
             while the filename had been set will not be erased.
SEE ALSO: writeNmzData, readNmzData, setNmzDataPath, rmNmzFiles
EXAMPLE:  example setNmzFilename; shows an example"
{
    desString("nmz_filename",nmz_filename_name);
    if(nmz_filename_name!="")
    {
        desInt("nmz_files_keep_switch",1);
    }
    else
    {
        desInt("nmz_files_keep_switch",0);
    }
}
example
{ "EXAMPLE:";echo = 2;
  setNmzDataPath("examples/");
  setNmzFilename("example1");
  //now the files for the exchange with Normaliz are examples/example1.SUFFIX
}

proc setNmzDataPath(string nmz_data_path_name)
"USAGE:   setNmzDataPath(string s);
CREATE:   @code{Normaliz::nmz_data_path} to save the given path @code{s}
NOTE:     The function sets the path for the exchange of data. By default the
          files will be created in the current directory.
          @* It seems that Singular cannot use filenames starting with @code{~}
             or @code{$HOME} in its input/output functions.
          @* You must also avoid path names starting with @code{/} if you work
             under Cygwin, since Singular and Normaliz interpret them in
             different ways.
SEE ALSO: writeNmzData, readNmzData, rmNmzFiles, setNmzFilename
EXAMPLE:  example setNmzDataPath; shows an example"
{
    desString("nmz_data_path",nmz_data_path_name);
    nmz_data_path=appendSlash(nmz_data_path);
}
example
{ "EXAMPLE:";echo = 2;
  setNmzDataPath("examples/");
  setNmzFilename("example1");
  //now the files for the exchange with Normalize are examples/example1.SUFFIX
}

proc writeNmzPaths();
"USAGE:   writeNmzPaths();
CREATE:   the file nmz_sing_exec.path where the path to the Normaliz executable
          is saved
          @* the file nmz_sing_data.path where the directory for the exchange
          of data is saved
NOTE:     Both files are saved in the current directory. If one of the names
          has not been defined, the corresponding file is created, but
          contains nothing.
SEE ALSO: setNmzDataPath, setNmzExecPath, startNmz
EXAMPLE:  example writeNmzPaths; shows an example
"{
    link outf=":w nmz_sing_exec.path";
    write(outf, queryString("nmz_exec_path"));
    close(outf);

    outf=":w nmz_sing_data.path";
    write(outf, queryString("nmz_data_path"));
    close(outf);
}
example
{ "EXAMPLE:";echo = 2;
  setNmzExecPath("../Normaliz/");
  writeNmzPaths();
  int dummy=system("sh","cat nmz_sing_exec.path");
  dummy=system("sh","cat nmz_sing_data.path");
}

proc startNmz()
"USAGE:   startNmz();
PURPOSE:  This function reads the files written by @code{writeNmzPaths()},
          retrieves the path names, and types them on the standard output
          (as far as they have been set). Thus, once the path names have been
          stored, a Normaliz session can simply be opened by this function.
SEE ALSO: setNmzDataPath, setNmzExecPath, writeNmzPaths
EXAMPLE:  example startNmz; shows an example
"
{
    link inf=":r nmz_sing_exec.path";
    string s=read(inf);
    int i,p;
    p=findWord("/",s,1);
    if(p!=-1)
    {
        for(i=size(s);i>=1;i--)
        {
            if(s[i]=="/")
            {
                s=s[1..i];
                break;
            }
        }
        desString("nmz_exec_path",s);
        "nmz_exec_path is",nmz_exec_path;
    }
    else
    {
        "nmz_exec_path not set";
    }

    inf=":r nmz_sing_data.path";
    s=read(inf);
    p=findWord("/",s,1);
    if(p!=-1)
    {
        for(i=size(s);i>=1;i--)
        {
            if(s[i]=="/")
            {
                s=s[1..i];
                break;
            }
        }
        desString("nmz_data_path",s);
        "nmz_data_path is",nmz_data_path;
    }
    else
    {
        "nmz_data_path not set";
    }
}
example
{ "EXAMPLE:"; echo=2;
  startNmz();
}

static proc getNmzFile()
{
    if(queryInt("nmz_files_keep_switch"))
    {
        return(queryString("nmz_data_path")+queryString("nmz_filename"));
    }
    else
    {
        return(queryString("nmz_filename"));
    }
}

static proc makeTempNmzDataPath()
{
    string testdir, testdir1;
    int i,dummy;

    testdir1="/tmp/nmz_sing_"+string(system("pid"));
    testdir=testdir1;
    while(fileExists(testdir))
    {
        i++;
        testdir=testdir1+string(i);
    }
    dummy=system("sh","mkdir "+ testdir);
    desString("nmz_filename",testdir+"/nmz"); //files are nmz+suffix in testdir
}

static proc eraseTempNmzDataPath();
{
    int dummy;

    string tmpdir=getNmzFile();
    tmpdir=tmpdir[1..size(tmpdir)-4]; // remove "/nmz"
    dummy=system("sh","rm -r "+tmpdir);
    setNmzFilename("");
}

static proc setNmzExec()
{
    return(queryString("nmz_exec_path")+"normaliz");
}

proc rmNmzFiles()
"USAGE:  rmNmzFiles();
PURPOSE: This function removes the files created for and by Normaliz, using
         the last filename specified.
         It needs an explicit filename set (see @ref{setNmzFilename}).
SEE ALSO: writeNmzData, readNmzData, setNmzFilename, setNmzDataPath
EXAMPLE:  example rmNmzFiles; shows an example
"{

    if(!queryInt("nmz_files_keep_switch"))
    {
        ERROR("rmNmzFiles: no filename specified");
    }

    list suffixes="in","gen","out","cst","typ","egn","esp","inv","tri","ht1",
                  "ext","dec", "lat", "mod";
    int i,dummy;
    string f;

    for(i=1;i<=size(suffixes);i++)
    {
        f=getNmzFile()+"."+suffixes[i];
        if (fileExists(f))
        {
            dummy=system("sh","rm "+f+ "&> /dev/null");
        }
    }
}
example
{ "EXAMPLE:"; echo=2;
  setNmzFilename("VeryInteresting");
  rmNmzFiles();
}



// parsing normaliz output

static proc digit(string s)
{
    if(s==" ") // skip blanks quickly
    {
        return(0);
    }

    if((s[1]>="0" && s[1]<="9")||s[1]=="-")
    {
        return(1);
    }
    return(0);
}

static proc nextWord(string s, int p)
{
    int j,sw,ew;

    for(;p<=size(s);p++) // must start with a letter
    {

        if((s[p]>="a" && s[p]<="z")||
             (s[p]>="A" && s[p]<="Z"))
        {
            sw=p; break;
        }
    }
    if(p>size(s))
    {
        return(-1,-1); // no word found
    }

    for(;p<=size(s);p++) // now numerals and -_ allowed
    {
        if(!((s[p]>="a" && s[p]<="z")||
             (s[p]>="A" && s[p]<="Z")||
             (s[p]>="0" && s[p]<="9")||
              s[p]=="_"||s[p]=="-"))
        {
            break;
        }
    }
    return(sw,p);
}

static proc getInt(string s, int p)
{
    string nst;
    int i,j,en,sn;

    for(;p<=size(s);p++)
    {

        if(digit(s[p]))
        {
            sn=p; break;
        }
    }
    if(not(sn))
    {
        return(0,-1); // -1 indicates: no number found
    }
    p++;
    for(;p<=size(s);p++)
    {
        if(!digit(s[p]))
        {
            en=p-1; break;
        }
    }
    if(p>size(s))
    {
        en=size(s);
    }
    nst="i="+s[sn,en-sn+1];
    execute(nst);
    return(i,p);
}


static proc getRational(string s, int p)
{
    string nst;
    int i,j,en,sn;

    for(;p<=size(s);p++)
    {
        if(digit(s[p]))
        {
            sn=p; break;
        }
    }
    if(not(sn))
    {
        return(0,-1); // -1 indicates: no number found
    }
    p++;
    int slash_at;
    for(;p<=size(s);p++)
    {
        if(s[p]=="/")
        {
            slash_at=p;
            p++;
            continue;
        }
        if(!digit(s[p]))
        {
            en=p-1; break;
        }
    }
    if(p>size(s))
    {
        en=size(s);
    }
    if(slash_at)
    {
        nst="i="+s[sn,slash_at-sn];
        execute(nst);
        nst="j="+s[slash_at+1,en-slash_at];
        execute(nst);
        return(i,p,j);
    }
    nst="i="+s[sn,en-sn+1];
    execute(nst);
    return(i,p);
}


static proc findWord(string s, string t, int p)
{
    for(;p<=size(t)-size(s)+1;p++)
    {
        if(t[p]==s[1])
        {
            if(t[p,size(s)]==s)
            {
                 return(p+size(s));
            }
        }
    }
    return(-1);
}


static proc skipEqualsign(string s,int p)
{
    for(;p<=size(s);p++)
    {
        if(s[p]=="=")
        {
            break;
        }
    }
    return(p+1);
}


// input and output to/from normaliz

//list must have pairs of intmat, nmz_mode
static proc doWriteNmzData(list #)
{
    string s;
    int i,j;
    link outf=":w "+ getNmzFile() +".in";  // also sets the filename

    intmat sgr;
    int num_rows, num_cols, n_mode;

    for (int k=1; k+1<=size(#); k=k+2) {
    //get data from the parameter list
        n_mode   = #[k+1];
        if (n_mode != -1) { //skip -1 mode
            sgr = #[k];
            num_rows = nrows(sgr);
            num_cols = ncols(sgr);

            write(outf,num_rows);
            write(outf,num_cols);

            for(i=1;i<=nrows(sgr);i++)
            {
                s="";
                for(j=1;j<=num_cols;j++)
                {
                    s=s+string(sgr[i,j])+" ";
                }
                write(outf,s);
            }
            if (n_mode == 20) {
                write(outf,"grading");}
            if (n_mode == 0) {
                write(outf,"integral_closure");}
            if (n_mode == 1) {
                write(outf,"normalization");}
            if (n_mode == 2) {
                write(outf,"polytope");}
            if (n_mode == 3) {
                write(outf,"rees_algebra");}
            if (n_mode == 4) {
                write(outf,"inequalities");}
            if (n_mode == 5) {
                write(outf,"equations");}
            if (n_mode == 6) {
                write(outf,"congruences");}
            if (n_mode == 10) {
                write(outf,"lattice_ideal");}
            write(outf,"");
        }
    }
    close(outf);
}


static proc prepareGrading(list #)
{
    if (size(#)==0) {
        return(0,-1); // mode -1 specifies discard the matrix
    }
    if (size(#)>1) {
        print(#);
        ERROR("To many parameters!");
    }
    intmat g = intmat(#[1],1,size(#[1]));
    return (g,20);
}


proc writeNmzData(intmat sgr, int n_mode, list #)
"USAGE:   writeNmzData(intmat M, int mode);
          writeNmzData(intmat M, int mode, intmat M2, int mode2, ...);
CREATE:   Creates an input file for Normaliz from the matrix M. The second
          parameter sets the mode. How the matrix is interpreted depends on the
          mode. See the Normaliz documentation for more information.

          It is also possible to give more than one pair of matrix and mode. In
          this case all matrices and modes are written. This can be used to
          combine modes 4,5,6.
          Use mode=20 to specify a grading.
NOTE:     Needs an explicit filename set. The filename is created from the
          current filename.
   @*     Note that all functions in normaliz.lib write and read their data
          automatically to and from the hard disk so that writeNmzData will
          hardly ever be used explicitly.
SEE ALSO: readNmzData, rmNmzFiles, setNmzFilename, setNmzDataPath
EXAMPLE:  example writeNmzData; shows an example"
{
    if(queryString("nmz_filename")=="")
    {
        ERROR("writeNmzData: no filename specified");
    }
    doWriteNmzData(list(sgr, n_mode) + #);
}
example
{ "EXAMPLE:"; echo=2;
  setNmzFilename("VeryInteresting");
  intmat sgr[3][3]=1,2,3,4,5,6,7,8,10;
  writeNmzData(sgr,1);
  int dummy=system("sh","cat VeryInteresting.in");

  intmat Hyperplanes[2][3] = 2,-1,0, // 2x-y >= 0
                             1, 1,0; //  x+y >= 0
  intmat Equation[1][3] = 0,1,-1;    // y = z
  intmat Congruence[1][4] = 1,0,0,3;  // x = 0 (3)
  writeNmzData(Hyperplanes,4,Equation,5,Congruence,6);
  dummy=system("sh","cat VeryInteresting.in");
}


proc readNmzData(string nmz_suffix)
"USAGE:  readNmzData(string suffix);
RETURN:  Reads an output file of Normaliz containing an integer matrix and
         returns it as an intmat. For example, this function is useful if one
         wants to inspect the support hyperplanes. The filename is created
         from the current  filename and the suffix given to the function.
NOTE:    Needs an explicit filename set by setNmzFilename.
   @*    Note that all functions in normaliz.lib write and read their data
         automatically so that readNmzData will usually not be used explicitly.
   @*    This function reads only the first matrix in a file!
SEE ALSO: writeNmzData, rmNmzFiles, setNmzFilename, setNmzDataPath
EXAMPLE:  example readNmzData; shows an example"
{
    if(queryString("nmz_filename")=="")
    {
        ERROR("readNmzData: no filename specified");
    }

    string s;
    int n_rows,n_cols;            //number of rows/columns
    int p;                     //position
    int i,j;
    int returnvalue;

    string filename = getNmzFile() + "."+ nmz_suffix;
    link in_f=":r "+ filename;
    s=read(in_f);
    close(in_f);

    p=1;
    (n_rows,p)=getInt(s,p);
    (n_cols,p)=getInt(s,p);
    if (n_rows <= 0 || n_cols <= 0) {
         intmat empty;
         return(empty);
    }
    intmat nmz_gen[n_rows][n_cols];
    for(i=1;i<=n_rows;i++)
    {
        for(j=1;j<=n_cols;j++)
        {
            (nmz_gen[i,j],p) = getInt(s,p);
        }
    }
    return(nmz_gen);
}
example
{ "EXAMPLE:"; echo=2;
  setNmzFilename("VeryInteresting");
  intmat sgr[3][3]=1,2,3,4,5,6,7,8,10;
  intmat sgrnormal=normaliz(sgr,0);
  readNmzData("cst");
}


// running normaliz (with options)

// component 1 is name of option
// 2 is default value
// 3 is command line option to be passed to Normaliz
// 4 indictes whether file "gen" is generated
// value 2 of 4 indicates "no influence"

static proc defNmzOptions()
{
    if(!defined(nmz_options)) // can be defined only once
    {
        list nmz_options=
        list("supp",0,"-s",0),
        list("triang",0,"-tT",0),
        list("volume",0,"-v",0),
        list("hvect",0,"-p",0),
        list("height1",0,"-1",0),
        list("normal",0,"-n",1),
        list("normal_l",0,"-N",1),
        list("hilb",0,"-h",1),
        list("dual",0,"-d",1),
        list("control",0,"-c",2),
        list("allf",0,"-a",2),
        list("errorcheck",0,"-e",2),
        list("bigint",0,"-B",2),
        list("threads",0,"-x=",2);
        export(nmz_options);
    }
}

proc setNmzOption(string s, int onoff)
"USAGE:   setNmzOption(string s, int onoff);
PURPOSE:  If @code{onoff=1} the option @code{s} is activated, and
          if @code{onoff=0} it is deactivated.
The Normaliz options are accessible via the following names:
@* @code{-s:  supp}
@* @code{-t:  triang}
@* @code{-v:  volume}
@* @code{-p:  hvect}
@* @code{-1:  height1}
@* @code{-n:  normal}
@* @code{-N:  normal_l}
@* @code{-h:  hilb}
@* @code{-d:  dual}
@* @code{-a:  allf}
@* @code{-c:  control}
@* @code{-e:  errorcheck}
@* @code{-B:  bigint} Use GMP for arbitrary precision integers
@* @code{-x=N:  threads} In this case the int parameter is used to set the
                         number of threads N, 0 means no explicit limiting.
                         
            In the next version of this library the options will be accessible
            via their standard Normaliz 3.0 names. 

SEE ALSO: showNmzOptions
EXAMPLE:  example setNmzOption; shows an example
"
{
    defNmzOptions();
    for(int i=1;i<=size(nmz_options);i++)
    {
        if(s==nmz_options[i][1])
        {
            nmz_options[i][2]=onoff;
            return(1);
        }
    }
    "Invalid option ", s;
    return(0);
}
example
{ "EXAMPLE:"; echo=2;
  setNmzOption("hilb",1);
  showNmzOptions();
}

static proc collectNmzOptions()
{
    defNmzOptions();
    string run_options=" -f ";
    desInt("GenGen",1); // indicates whether "gen" is generated
    for(int i=1;i<=size(nmz_options);i++)
    {
        if(nmz_options[i][2])
        {
            run_options=run_options+nmz_options[i][3];
                if (nmz_options[i][1]=="threads") {
                    run_options=run_options+string(nmz_options[i][2]);
                }
                run_options=run_options+" ";
            if(nmz_options[i][4]!=2)
            {
                GenGen=nmz_options[i][4];
            }
        }
    }
    return(run_options+" ");
}

proc showNmzOptions()
"USAGE:   showNmzOptions();
RETURN:   Returns the string of activated options.
NOTE:     This string is used as parameter when calling Normaliz.
SEE ALSO: setNmzOption
EXAMPLE:  example showNmzOption; shows an example
"
{
    return(collectNmzOptions());
}
example
{ "EXAMPLE:"; echo=2;
  setNmzOption("hilb",1);
  showNmzOptions();
}


static proc runNormaliz(intmat sgr, int nmz_mode, list #)
{
    if(!queryInt("nmz_files_keep_switch"))
    {
        makeTempNmzDataPath();
    }

    doWriteNmzData(list(sgr, nmz_mode) + #);

    if(queryInt("nmz_files_keep_switch"))
    {
       int dummy=system("sh",setNmzExec()+ collectNmzOptions() + getNmzFile());
    }
    else
    {
        string gotodir="/tmp";
        string fname=getNmzFile();
        fname=fname[6..size(fname)];
        string exec="cd "+gotodir+" ; ";
        exec=exec+setNmzExec()+ collectNmzOptions()+" ";
        exec=exec+fname+" ;";
        int dummy=system("sh",exec);
    }

    if(!GenGen) // return input matrix if "gen" has not been generated
    {
        if(!queryInt("nmz_files_keep_switch"))
        {
            eraseTempNmzDataPath();
        }
        return(sgr);
    }
    intmat Gen=readNmzData("gen");

    if(!defined(Num_Invs))
    {
        list Num_Invs;
        export Num_Invs;
    }
    Num_Invs=getNuminvs();

    if(!queryInt("nmz_files_keep_switch"))
    {
        eraseTempNmzDataPath();
    }

    return(Gen);

}

proc normaliz(intmat sgr,int nmz_mode, list #)
"USAGE:   normaliz(intmat sgr,int nmz_mode);
          normaliz(intmat sgr, int nmz_mode, intmat sgr2, int nmz_mode2, ...);
RETURN:   The function applies Normaliz to the parameter sgr in the mode set
          by nmz_mode. The function returns the intmat defined by the file
          with suffix gen.           
          
          It is also possible to give more than one pair of matrix and mode.          
          In this case all matrices and modes are used. 
          
          In this version one must use the old numerical types of input matrices
          according to the following table:
          
@* @code{0:  cone}
@* @code{1:  cone_and_lattice}
@* @code{2:  polytope}
@* @code{3:  rees_algebra}
@* @code{4:  inequalities}
@* @code{5:  equations}
@* @code{6:  congruences}
@* @code{10:  lattice_ideal}
@* @code{20:  grading}

          In the next vfersion all input types of Normaliz 3.0 will be accessible
          via their names. See the Normaliz manual for more information.
          
NOTE:     You will find procedures for many applications of Normaliz in this
          library, so the explicit call of this procedure may not be necessary.
SEE ALSO: intclToricRing, normalToricRing, ehrhartRing, intclMonIdeal,
          torusInvariants, diagInvariants, finiteDiagInvariants, intersectionValRings,
             intersectionValRingIdeals
EXAMPLE:  example normaliz; shows an example
"
{
    return(runNormaliz(sgr,nmz_mode,#));
}
example
{ "EXAMPLE:"; echo=2;
  ring R=0,(x,y,z),dp;
  intmat M[3][2]=3,1,
                 3,2,
                 1,3;
  normaliz(M,1);

  intmat Hyperplanes[2][3] = 2,-1,0, // 2x-y >= 0
                             1, 1,0; //  x+y >= 0
  intmat Equation[1][3] = 0,1,-1;    // y = z
  intmat Congruence[1][4] = 1,0,0,3;  // x = 0 (3)
  normaliz(Hyperplanes,4,Equation,5,Congruence,6);
}


// retrieving normaliz numerical invariants

static proc getNuminvs()
{
    string s;
    list num_invs;
    int p,sw,v_length,i,dummy_int;
    intvec dummy_vec;
    string type_inv,name_inv,dummy_bool;

    link in_f=":r "+ getNmzFile() + "."+"inv";
    s=read(in_f);

    p=1;
    while(p<size(s))
    {
        (sw,p)=nextWord(s,p);
        if(sw==-1)
        {
            break;
        }
        type_inv=s[sw..p-1];
        if(type_inv=="vector")
        {
            (v_length,p)=getInt(s,p);
            (sw,p)=nextWord(s,p);
            name_inv=s[sw..p-1];
            if(name_inv=="h-vector")
            {
                name_inv="h_vector";
            }
            if(name_inv!="hilbert_polynomial"
              && name_inv!="hilbert_quasipolynomial")
            {
                for(i=1;i<=v_length;i++)
                {
                    if(i==1)
                    {
                        (dummy_int,p)=getInt(s,p);
                        dummy_vec=dummy_int;
                    }
                    else
                    {
                        (dummy_int,p)=getInt(s,p);
                        dummy_vec=dummy_vec,dummy_int;
                    }
                }
                num_invs=num_invs+list(list(name_inv,dummy_vec,"intvec"));
            }
            else
            {
                p=skipEqualsign(s,p);
            }
        }
        if(type_inv=="integer")
        {
            (sw,p)=nextWord(s,p);
            name_inv=s[sw..p-1];
            if (name_inv!="hilbert_quasipolynomial_denom") {
              (dummy_int,p)=getInt(s,p);
              num_invs=num_invs+list(list(name_inv,dummy_int,"int"));
            }
        }
        if(type_inv=="boolean")
        {
            (sw,p)=nextWord(s,p);
            name_inv=s[sw..p-1];
            p=skipEqualsign(s,p);
            (sw,p)=nextWord(s,p);
            dummy_bool=s[sw..p-1];
            dummy_int=0;
            if(dummy_bool=="true")
            {
                dummy_int=1;
            }
            num_invs=num_invs+list(list(name_inv,dummy_int,"int"));
        }
    }
    return(num_invs);
}

proc showNuminvs()
"USAGE:   showNuminvs();
PURPOSE:  prints the numerical invariants
SEE ALSO: exportNuminvs
EXAMPLE:  example showNuminvs(); shows an example
"
{
    list dummy;
    int i;
    for(i=1;i<=size(Num_Invs);i++)
    {
        dummy=Num_Invs[i];
        dummy[1],":", dummy[2];
    }
}
example
{ "EXAMPLE:"; echo=2;
  ring R=0,(x,y,z,t),dp;
  ideal I=x3,x2y,y3;
  list l=intclMonIdeal(I);
  showNuminvs();
}


proc exportNuminvs()
"USAGE:   exportNuminvs();
CREATE:   Creates top-level variables which contain the numerical invariants.
          Depending on the options of normaliz different invariants are
          calculated. Use showNuminvs (@ref{showNuminvs}) to see which
          invariants are available.
SEE ALSO: showNuminvs
EXAMPLE:  example exportNuminvs; shows an example
"
{
    list dummy;
    int i;
    string s;
    for(i=1;i<=size(Num_Invs);i++)
    {
        dummy=Num_Invs[i];
        s=dummy[3]+" nmz_" + dummy[1] + "=dummy[2]; exportto(Top," + "nmz_" + dummy[1] + ");";
        execute(s);
    }
}
example
{ "EXAMPLE:"; echo=2;
  ring R=0,(x,y,z,t),dp;
  ideal I=x3,x2y,y3;
  list l=intclMonIdeal(I);
  exportNuminvs();
  // for example, now the following variables are set:
  nmz_hilbert_basis_elements;
  nmz_number_extreme_rays;
  nmz_rank;
  nmz_number_support_hyperplanes;
  nmz_multiplicity;
  nmz_primary;
}


// intmats to/from monomials

proc mons2intmat(ideal I)
"USAGE:   mons2intmat(ideal I);
RETURN:   Returns the intmat whose rows represent the leading exponents of the
          (non-zero) elements of I. The length of each row is nvars(basering).
SEE ALSO: intmat2mons
EXAMPLE:  example mons2intmat; shows an example"
{
    int i,j,k;
    intmat expo_vecs[size(I)][nvars(basering)];
    intvec expo_v;

    k=0;
    for(i=1;i<=ncols(I);i++)
    {
        if(I[i]!=0)
        {
            k++;
            expo_v=leadexp(I[i]);
            for(j=1;j<=nvars(basering);j++)
            {
                expo_vecs[k,j]=expo_v[j];
            }
        }
    }
    return(expo_vecs);
}
example
{ "EXAMPLE:"; echo=2;
  ring R=0,(x,y,z),dp;
  ideal I=x2,y2,x2yz3;
  mons2intmat(I);
}

proc intmat2mons(intmat expo_vecs)
"USAGE:   intmat2mons(intmat M);
RETURN:   an ideal generated by the monomials which correspond to the exponent
          vectors given by the rows of @code{M}
NOTE:     The number of variables in the basering @code{nvars(basering)} has to
          be at least the number of columns @code{ncols(M)}, otherwise the
          function exits with an error.
          is thrown (see @ref{ERROR}).
SEE ALSO: mons2intmat
EXAMPLE:  example intmat2mons; shows an example
"
{
    int i,j;
    poly m;
    ideal mons;

    if(nvars(basering)<ncols(expo_vecs))
    {
        ERROR("intmat2mons: not enough variables in ring");
    }

    for(i=1;i<=nrows(expo_vecs);i++)
    {
        m=1;
        for(j=1;j<=ncols(expo_vecs);j++)
        {
            m=m*var(j)^expo_vecs[i,j];
        }
        mons=mons,m;
    }
     mons=simplify(mons,2);    // get rid of starting 0
     return(mons);
}
example
{ "EXAMPLE:"; echo=2;
  ring R=0,(x,y,z),dp;
  intmat expo_vecs[3][3] =
  2,0,0,
  0,2,0,
  2,1,3;
  intmat2mons(expo_vecs);
}

static proc intmat2monsSel(intmat expo_vecs, int d)
{
    int i,j;
    poly m;
    ideal mons;

    if(nvars(basering)<ncols(expo_vecs)-1)
    {
        ERROR("intmat2monsSel: not enough variables in ring");
    }

    for(i=1;i<=nrows(expo_vecs);i++)
    {
        if(expo_vecs[i,ncols(expo_vecs)]==d)
        {
            m=1;
            for(j=1;j<=ncols(expo_vecs)-1;j++)
            {
                m=m*var(j)^expo_vecs[i,j];
            }
            mons=mons,m;
        }
    }
    mons=simplify(mons,2);    // get rid of starting 0
    return(mons);
}


proc binomials2intmat(ideal I)
"USAGE:   binomials2intmat(ideal I);
RETURN:   Returns the intmat whose rows represent the exponents of the
          (non-zero) elements of I which have to be binomials.
          The length of each row is nvars(basering).
SEE ALSO: mons2intmat, intmat2mons
EXAMPLE:  example binomials2intmat; shows an example"
{
    int i,j,k;
    intmat expo_vecs[size(I)][nvars(basering)];
    intvec expo_v;

    k=0;
    poly f;

    for(i=1; i<=ncols(I); i++)
    {
        if( I[i] != 0 )
        {
            k++;
            f = I[i];
            if (leadcoef(f) != 1) {f = -f};  //works in all characteristics
            if (size(f)!=2 || leadcoef(f)!=1 || leadcoef(f[2])!=-1)
            {
                ERROR(string("normalToricRing: binomial ideal expected: generator ",i,": ",I[i]));
            }

            expo_v = leadexp(f)-leadexp(f[2]);
            for(j=1;j<=nvars(basering);j++)
            {
                expo_vecs[k,j]=expo_v[j];
            }
        }
    }
    return(expo_vecs);
}
example
{ "EXAMPLE:"; echo=2;
  ring S = 37,(u,v,w,x,y,z),dp;
  ideal I = u2v-xyz, ux2-vyz, uvw-y2z;
  binomials2intmat(I);
}


// integral closure of rings and ideals

static proc runIntclToricRing(ideal I, int nmz_mode, list #)
{
    intmat expo_vecs=mons2intmat(I);

    string dummy=collectNmzOptions(); // only to set GenGen
    return( intmat2mons( runNormaliz(expo_vecs,nmz_mode, prepareGrading(#)) ) );
}

proc intclToricRing(ideal I, list #)
"USAGE:   intclToricRing(ideal I);
          intclToricRing(ideal I, intvec grading);
RETURN:   The toric ring S is the subalgebra of the basering generated by
          the leading monomials of the elements of I (considered as a list
          of polynomials). The function computes the integral
          closure T of S in the basering and returns an ideal listing
          the algebra generators of T over the coefficient field.
@*        The function returns the input ideal I if one of the options
          @code{supp}, @code{triang}, @code{volume}, or @code{hseries}
          has been activated.
          However, in this case some numerical invariants are computed, and
          some other data may be contained in files that you can read into
          Singular (see @ref{showNuminvs}, @ref{exportNuminvs}).
NOTE:     A mathematical remark: the toric ring depends on the list of
          monomials given, and not only on the ideal they generate!
SEE ALSO:  normalToricRing, ehrhartRing, intclMonIdeal
EXAMPLE:   example intclToricRing; shows an example
"
{
    return(runIntclToricRing(I,0,#));
}
example
{ "EXAMPLE:"; echo=2;
  ring R=37,(x,y,t),dp;
  ideal I=x3,x2y,y3;
  intclToricRing(I);
  showNuminvs();
  //now the same example with another grading
  intvec grading = 2,3,1;
  intclToricRing(I,grading);
  showNuminvs();

}

proc normalToricRing(ideal I, list #)
"USAGE:   normalToricRing(ideal I);
          normalToricRing(ideal I, intvec grading);
RETURN:   The toric ring S is the subalgebra of the basering generated by the
          leading monomials of the elements of I (considered as a list of
          polynomials). The function computes the
          normalisation T of S and returns an ideal listing the algebra
          generators of T over the coefficient field.
@*        The function returns the input ideal I if one of the options
          @code{supp}, @code{triang}, @code{volume}, or @code{hseries}
          has been activated.
          However, in this case some numerical invariants are computed, and
          some other data may be contained in files that you can read into
          Singular (see @ref{showNuminvs}, @ref{exportNuminvs}).
NOTE:     A mathematical remark: the toric ring depends on the list of
          monomials given, and not only on the ideal they generate!
SEE ALSO: intclToricRing, ehrhartRing, intclMonIdeal, normalToricRingFromBinomials
EXAMPLE:  example normalToricRing; shows an example
"
{
    return(runIntclToricRing(I,1,#));
}
example
{ "EXAMPLE:"; echo=2;
  ring  R = 37,(x,y,t),dp;
  ideal I = x3,x2y,y3;
  normalToricRing(I);
}


proc normalToricRingFromBinomials(ideal I, list #)
"USAGE:   normalToricRingFromBinomials(ideal I);
          normalToricRingFromBinomials(ideal I, intvec grading);
RETURN:   @texinfo
@tex
The ideal $I$ is generated by binomials of type $X^a-X^b$ (multiindex notation)
in the surrounding polynomial ring $K[X]=K[X_1,...,X_n]$. The binomials
represent a congruence on the monoid ${Z}^n$ with residue monoid $M$.
Let $N$ be the image of $M$ in gp($M$)/torsion. Then $N$ is universal in the
sense that every homomorphism from $M$ to an affine monoid factors through $N$.
If $I$ is a prime ideal, then $K[N]= K[X]/I$. In general, $K[N]=K[X]/P$ where
$P$ is the unique minimal prime ideal of $I$ generated by binomials of type
$X^a-X^b$.

The function computes the normalization of $K[N]$ and returns a newly created
polynomial ring of the same Krull dimension, whose variables are
$x(1),...,x(n-r)$, where $r$ is the rank of the matrix with rows $a-b$.
(In general there is no canonical choice for such an embedding.)
Inside this polynomial ring there is an ideal $I$ which lists the algebra
generators of the normalization of $K[N]$.
@end tex
@end texinfo
@*        The function returns the input ideal I if one of the options
          @code{supp}, @code{triang}, @code{volume}, or @code{hseries}
          has been activated.
          However, in this case some numerical invariants are computed, and
          some other data may be contained in files that you can read into
          Singular (see @ref{showNuminvs}, @ref{exportNuminvs}).
SEE ALSO: intclToricRing, normalToricRing, ehrhartRing, intclMonIdeal
EXAMPLE:  example normalToricRing; shows an example
"
{
    intmat expo_vecs = binomials2intmat(I);
    string dummy=collectNmzOptions(); // only to set GenGen
    intmat result = runNormaliz(expo_vecs,10,prepareGrading(#));

    list baseringlist = ringlist(basering);
    ring S = (baseringlist[1]),(x(1..ncols(result))),dp;
    ideal I = intmat2mons(result);
    export(I);
    return (S);
}
example
{ "EXAMPLE:"; echo=2;
  ring R = 37,(u,v,w,x,y,z),dp;
  ideal I = u2v-xyz, ux2-wyz, uvw-y2z;
  def S = normalToricRingFromBinomials(I);
  setring S;
  I;
}

static proc runIntclMonIdeal(ideal I, int nmz_mode, list #)
{
    intmat expo_vecs=mons2intmat(I);
    int i,last_comp;

    // we test if there is room for the Rees algebra

    for(i=1;i<=nrows(expo_vecs);i++)
    {
        if(expo_vecs[i,ncols(expo_vecs)]!=0)
        {
            last_comp=1;  break; // no
        }
    }

    string dummy=collectNmzOptions(); // only to set GenGen

    //adjust size of input matrix
    if (!last_comp) { // remove last component
        intmat tmp[nrows(expo_vecs)][ncols(expo_vecs)-1]
               = expo_vecs[1..nrows(expo_vecs),1..(ncols(expo_vecs)-1)];
        expo_vecs = tmp;
    }
    intmat nmz_data=runNormaliz(expo_vecs,nmz_mode,prepareGrading(#));

    if(last_comp)
    {
        ideal I1=intmat2monsSel(nmz_data,1);
        return(list(I1));
    }
    else
    {
        ideal I1=intmat2monsSel(nmz_data,1);
        ideal I2=intmat2mons(nmz_data);
        return(list(I1,I2));
    }
}

proc ehrhartRing(ideal I)
"USAGE:    ehrhartRing(ideal I);
RETURN:    The exponent vectors of the leading monomials of the elements of I
           are considered as points of a lattice polytope P.
           The Ehrhart ring of a (lattice) polytope P is the monoid algebra
           defined by the monoid of lattice points in the cone over the
           polytope P; see Bruns and Gubeladze, Polytopes, Rings, and K-theory,
           Springer 2009, pp. 228, 229.
           The function returns a list of ideals:
@*         (i) If the last ring variable is not used by the monomials, it is
               treated as the auxiliary variable of the Ehrhart ring. The
               function returns two ideals, the first containing the monomials
               representing all the lattice points of the polytope, the second
               containing the algebra generators of the Ehrhart ring over the
               coefficient field.
@*         (ii) If the last ring variable is used by the monomials, the list
                returned contains only one ideal, namely the monomials
                representing the lattice points of the polytope.
@*
@*        The function returns the a list containing the input ideal I if one
          of the options @code{supp}, @code{triang}, @code{volume}, or
          @code{hseries} has been activated.
          However, in this case some numerical invariants are computed, and
          some other data may be contained in files that you can read into
          Singular (see @ref{showNuminvs}, @ref{exportNuminvs}).
NOTE:      A mathematical remark: the Ehrhart ring depends on the list of
           monomials given, and not only on the ideal they generate!
SEE ALSO: intclToricRing, normalToricRing, intclMonIdeal
EXAMPLE:  example ehrhartRing; shows an example
"
{
    return(runIntclMonIdeal(I,2));
}
example
{ "EXAMPLE:"; echo=2;
  ring R=37,(x,y,t),dp;
  ideal J=x3,x2y,y3,xy2t7;
  ehrhartRing(J);
}

proc intclMonIdeal(ideal I, list #)
"USAGE:   intclMonIdeal(ideal I);
          intclMonIdeal(ideal I, intvec grading);
RETURN:   The exponent vectors of the leading monomials of the elements of I
          are considered as generators of a monomial ideal for which the
          normalization of its Rees algebra is computed. For a Definiton of the
          Rees algebra (or Rees ring) see Bruns and Herzog, Cohen-Macaulay
          rings, Cambridge University Press 1998, p. 182.
          The function returns a list of ideals:
@* (i) If the last ring variable is not used by the monomials, it is treated
       as the auxiliary variable of the Rees algebra. The function returns two
       ideals, the first containing the monomials generating the integral
       closure of the monomial ideal, the second containing the algebra
         generators of the normalization of the Rees algebra.
@* (ii) If the last ring variable is used by the monomials, the list returned
        contains only one ideal, namely the monomials generating the integral
        closure of the ideal.
@*        The function returns the a list containing the input ideal I if one
          of the options @code{supp}, @code{triang}, @code{volume}, or
          @code{hseries} has been activated.
          However, in this case some numerical invariants are computed, and
          some other data may be contained in files that you can read into
          Singular (see @ref{showNuminvs}, @ref{exportNuminvs}).
SEE ALSO: intclToricRing, normalToricRing, ehrhartRing
EXAMPLE:  example intclMonIdeal; shows an example
"
{
    return(runIntclMonIdeal(I,3,#));
}
example
{ "EXAMPLE"; echo=2;
    ring R=0,(x,y,z,t),dp;
    ideal I=x^2,y^2,z^3;
    list l=intclMonIdeal(I);
    l[1]; // integral closure of I
    l[2];  // monomials generating the integral closure of the Rees algebra
}

// torus invariants and valuation rings and ideals

proc torusInvariants(intmat E, list #)
"USAGE:   torusInvariants(intmat A);
          torusInvariants(intmat A, intvec grading);
RETURN:   @texinfo
Returns an ideal representing the list of monomials generating the ring of
invariants as an algebra over the coefficient field.
@tex
$R^T$.
@end tex
@*        The function returns the ideal given by the input matrix A if one of
          the options @code{supp}, @code{triang}, @code{volume}, or
          @code{hseries} has been activated.
          However, in this case some numerical invariants are computed, and
          some other data may be contained in files that you can read into
          Singular (see @ref{showNuminvs}, @ref{exportNuminvs}).
@end texinfo
BACKGROUND: @texinfo
@tex
 Let $T = (K^*)^r$ be the $r$-dimensional torus acting on the polynomial ring
 $R = K[X_1 ,\ldots,X_n]$ diagonally. Such an action can be described as
 follows: there are integers $a_{i,j}$, $i=1,\ldots,r$, $j=1,\ldots,n$, such
 that $(\lambda_1,\ldots,\lambda_r)\in T$ acts by the substitution
$$ X_j \mapsto \lambda_1^{a_{1,j}} \cdots \lambda_r^{a_{r,j}}X_j,
   \quad j=1,\ldots,n.$$
In order to compute the ring of invariants $R^T$ one must specify the matrix
$A=(a_{i,j})$.
@end tex
@end texinfo
SEE ALSO: diagInvariants, finiteDiagInvariants, intersectionValRings,
          intersectionValRingIdeals
EXAMPLE:  example torusInvariants; shows an example
"
{
    if(nvars(basering)!=ncols(E))
    {
        ERROR("torusInvariants: wrong number of columns in matrix");
    }

    string dummy=collectNmzOptions();  // only to set GenGen

    return( intmat2mons( runNormaliz(E,5,prepareGrading(#)) ) );
}
example
{ "EXAMPLE:"; echo=2;
  ring R=0,(x,y,z,w),dp;
  intmat E[2][4] = -1,-1,2,0, 1,1,-2,-1;
  torusInvariants(E);
}

proc finiteDiagInvariants(intmat C, list #)
"USAGE:   finiteDiagInvariants(intmat U);
          finiteDiagInvariants(intmat U, intvec grading);
RETURN:   @texinfo
@tex
This function computes the ring of invariants of a finite abelian group $G$
acting diagonally on the surrounding polynomial ring $K[X_1,...,X_n]$. The
group is the direct product of cyclic groups generated by finitely many
elements $g_1,...,g_w$. The element $g_i$ acts on the indeterminate $X_j$ by
$g_i(X_j)=\lambda_i^{u_{ij}}X_j$ where $\lambda_i$ is a primitive root of
unity of order equal to $ord(g_i)$. The ring of invariants is generated by all
monomials satisfying the system
$u_{i1}a_1+\ldots+u_{in} a_n \equiv 0$ mod ord$(g_i)$, $i=1,\ldots,w$.
The input to the function is the $w\times(n+1)$ matrix $U$ with rows
$u_{i1}\ldots u_{in}$ ord$(gi)$, $i=1,\ldots,w$. The output is a monomial ideal
listing the algebra generators of the subalgebra of invariants
{$R^G=\{f\in R : g_i f = f$ for all $i=1,\ldots,w\}$}.
@end tex
@end texinfo
@*        The function returns the ideal given by the input matrix C if one of
          the options @code{supp}, @code{triang}, @code{volume}, or
          @code{hseries} has been activated.
          However, in this case some numerical invariants are computed, and
          some other data may be contained in files that you can read into
          Singular (see @ref{showNuminvs}, @ref{exportNuminvs}).
NOTE:
SEE ALSO: torusInvariants, diagInvariants, intersectionValRings,
          intersectionValRingIdeals
EXAMPLE:  example finiteDiagInvariants; shows an example
"
{
    if(nvars(basering)!=ncols(C)-1)
    {
        ERROR("finiteDiagInvariants: wrong number of columns in matrix");
    }

    string dummy=collectNmzOptions();  // only to set GenGen

    return( intmat2mons( runNormaliz(C,6,prepareGrading(#)) ) );
}
example
{ "EXAMPLE:"; echo=2;
  ring R = 0,(x,y,z,w),dp;
  intmat C[2][5] = 1,1,1,1,5, 1,0,2,0,7;
  finiteDiagInvariants(C);
}

proc diagInvariants(intmat E, intmat C, list #)
"USAGE:   diagInvariants(intmat A, intmat U);
          diagInvariants(intmat A, intmat U, intvec grading);
RETURN:   @texinfo
@tex
This function computes the ring of invariants of a diagonalizable group
$D = T\times G$ where $T$ is a torus and $G$ is a finite abelian group, both
acting diagonally on the polynomial ring $K[X_1,\ldots,X_n]$. The group
actions are specified by the input matrices A and U. The first matrix specifies
the torus action, the second the action of the finite group. See
torusInvariants and finiteDiagInvariants for more detail. The output is a
monomial ideal listing the algebra generators of the subalgebra of invariants.
@end tex
@end texinfo
@*        The function returns the ideal given by the input matrix A if one of
          the options @code{supp}, @code{triang}, @code{volume}, or
          @code{hseries} has been activated.
          However, in this case some numerical invariants are computed, and
          some other data may be contained in files that you can read into
          Singular (see @ref{showNuminvs}, @ref{exportNuminvs}).
SEE ALSO: torusInvariants, finiteDiagInvariants, intersectionValRings, intersectionValRingIdeals
EXAMPLE:  example diagInvariants; shows an example
"
{
    if(nvars(basering)!=ncols(E) || nvars(basering)!=ncols(C)-1)
    {
        ERROR("diagInvariants: wrong number of columns in matrix");
    }

    string dummy=collectNmzOptions();  // only to set GenGen

    return( intmat2mons( runNormaliz(E,5,C,6,prepareGrading(#)) ) );
}
example
{ "EXAMPLE:"; echo=2;
  ring R=0,(x,y,z,w),dp;
  intmat E[2][4] = -1,-1,2,0, 1,1,-2,-1;
  intmat C[2][5] = 1,1,1,1,5, 1,0,2,0,7;
  diagInvariants(E,C);
}

proc intersectionValRings(intmat V, list #)
"USAGE:   intersectionValRings(intmat V, intvec grading);
RETURN:   The function returns a monomial ideal, to be considered as the list
          of monomials generating @math{S} as an algebra over the coefficient
          field.
BACKGROUND: @texinfo
@tex
A discrete monomial valuation $v$ on $R = K[X_1 ,\ldots,X_n]$ is determined by
the values $v(X_j)$ of the indeterminates. This function computes the
subalgebra $S = \{ f \in R : v_i ( f ) \geq 0,\ i = 1,\ldots,r\}$ for several
such valuations $v_i$, $i=1,\ldots,r$. It needs the matrix $V = (v_i(X_j))$ as
its input.
@end tex
@end texinfo
@*        The function returns the ideal given by the input matrix V if one of
          the options @code{supp}, @code{triang}, @code{volume}, or
          @code{hseries} has been activated.
          However, in this case some numerical invariants are computed, and
          some other data may be contained in files that you can read into
          Singular (see @ref{showNuminvs}, @ref{exportNuminvs}).
SEE ALSO: torusInvariants, diagInvariants, finiteDiagInvariants, intersectionValRingIdeals
EXAMPLE:  example intersectionValRings; shows an example
"
{

    if(nvars(basering)!=ncols(V))
    {
        ERROR("intersectionValRings: wrong number of columns in matrix");
    }

    intmat V1[nrows(V)+ncols(V)][ncols(V)];
    int i,j;

    for(i=1;i<=ncols(V);i++)
    {
        V1[i,i]=1;
    }
    for(i=1;i<=nrows(V);i++)
    {
        for(j=1;j<=ncols(V);j++)
        {
            V1[i+ncols(V),j]=V[i,j];
        }
    }


    string dummy=collectNmzOptions();  // only to set GenGen

/*    if(!GenGen) // return V
    {
        runNormaliz(V1,4,prepareGrading(#));
        return(V);
    }
*/
    return(intmat2mons(runNormaliz(V1,4,prepareGrading(#))));
}
example
{ "EXAMPLE:"; echo=2;
  ring R=0,(x,y,z,w),dp;
  intmat V0[2][4]=0,1,2,3, -1,1,2,1;
  intersectionValRings(V0);
}

proc intersectionValRingIdeals(intmat V, list #)
"USAGE:   intersectionValRingIdeals(intmat V);
          intersectionValRingIdeals(intmat V, intvec grading);
RETURN:   The function returns two ideals, both to be considered as lists of
          monomials. The
          first is the system of monomial generators of @math{S}, the second
          the system of generators of @math{M}.
@*        The function returns a list consisting of the ideal given by the
          input matrix T if one of the options @code{supp}, @code{triang}, or
          @code{hvect} has been activated.
          However, in this case some numerical invariants are computed, and
          some other data may be contained in files that you can read into
          Singular (see @ref{showNuminvs}, @ref{exportNuminvs}).
BACKGROUND: @texinfo
@tex
A discrete monomial valuation $v$ on $R = K[X_1 ,\ldots,X_n]$ is determined by
the values $v(X_j)$ of the indeterminates. This function computes the
subalgebra $S = \{ f \in R : v_i ( f ) \geq 0,\ i = 1,\ldots,r\}$ for several
such valuations $v_i$, $i=1,\ldots,r$. It needs the matrix $V = (v_i(X_j))$ as
its input.

This function simultaneously determines the $S$-submodule
$M = \{ f \in R : v_i(f) \geq w_i ,\ i = 1,\ldots,r\}$ for integers
$w_1,\ldots\,w_r$. (If $w_i \geq 0$ for all $i$, $M$ is an ideal of $S$.)
The numbers $w_i$ form the $(n+1)$th column of the input matrix.
@end tex
@end texinfo
NOTE:   The function also gives an error message if the matrix V has the
        wrong number of columns.
SEE ALSO: torusInvariants, diagInvariants, finiteDiagInvariants, intersectionValRings
EXAMPLE:  example intersectionValRingIdeals; shows an example
"
{
    if(nvars(basering)!=ncols(V)-1)
    {
        ERROR("intersectionValRingIdeals: wrong number of columns in matrix");
    }

    intmat V1[nrows(V)+ncols(V)][ncols(V)];
    int i,j;

    for(i=1;i<=ncols(V);i++)
    {
        V1[i,i]=1;
    }
    for(i=1;i<=nrows(V);i++)
    {
        for(j=1;j<=ncols(V);j++)
        {
            V1[i+ncols(V),j]=V[i,j];
        }
    }
    for(i=1;i<=nrows(V);i++)
    {
        V1[i+ncols(V),ncols(V)]=-V1[i+ncols(V),ncols(V)];
    }

    string dummy=collectNmzOptions();  // only to set GenGen

    intmat nmz_data=runNormaliz(V1,4,prepareGrading(#));

    ideal I1=intmat2monsSel(nmz_data,0);
    ideal I2=intmat2monsSel(nmz_data,1);
    return(list(I1,I2));
}
example
{ "EXAMPLE:"; echo=2;
 ring R=0,(x,y,z,w),dp;
 intmat V[2][5]=0,1,2,3,4, -1,1,2,1,3;
 intersectionValRingIdeals(V);
}