/****************************************
* Computer Algebra System SINGULAR *
****************************************/
/***************************************************************
* File: sca.cc
* Purpose: supercommutative kernel procedures
* Author: motsak (Oleksandr Motsak)
* Created: 2006/12/18
* Version: $Id: sca.cc,v 1.33 2009-03-02 17:04:52 motsak Exp $
*******************************************************************/
// set it here if needed.
#define OUTPUT 0
#define MYTEST 0
#if MYTEST
#define OM_CHECK 4
#define OM_TRACK 5
#endif
// #define PDEBUG 2
#include "mod2.h"
#ifdef HAVE_PLURAL
// for
#define PLURAL_INTERNAL_DECLARATIONS
#include "sca.h"
#include "gring.h"
#include "febase.h"
#include "p_polys.h"
#include "kutil.h"
#include "ideals.h"
#include "intvec.h"
#include "polys.h"
#include "ring.h"
#include "numbers.h"
#include "matpol.h"
#include "kbuckets.h"
#include "kstd1.h"
#include "sbuckets.h"
#include "prCopy.h"
#include "p_Mult_q.h"
#include "p_MemAdd.h"
#include "kutil.h"
#include "kstd1.h"
#include "weight.h"
// poly functions defined in p_Procs :
// return pPoly * pMonom; preserve pPoly and pMonom.
poly sca_pp_Mult_mm(const poly pPoly, const poly pMonom, const ring rRing, poly &);
// return pMonom * pPoly; preserve pPoly and pMonom.
poly sca_mm_Mult_pp(const poly pMonom, const poly pPoly, const ring rRing);
// return pPoly * pMonom; preserve pMonom, destroy or reuse pPoly.
poly sca_p_Mult_mm(poly pPoly, const poly pMonom, const ring rRing);
// return pMonom * pPoly; preserve pMonom, destroy or reuse pPoly.
poly sca_mm_Mult_p(const poly pMonom, poly pPoly, const ring rRing);
// compute the spolynomial of p1 and p2
poly sca_SPoly(const poly p1, const poly p2, const ring r);
poly sca_ReduceSpoly(const poly p1, poly p2, const ring r);
// Modified Plural's Buchberger's algorithmus.
ideal sca_gr_bba(const ideal F, const ideal Q, const intvec *, const intvec *, kStrategy strat);
// Modified modern Sinuglar Buchberger's algorithm.
ideal sca_bba(const ideal F, const ideal Q, const intvec *w, const intvec *, kStrategy strat);
// Modified modern Sinuglar Mora's algorithm.
ideal sca_mora(const ideal F, const ideal Q, const intvec *w, const intvec *, kStrategy strat);
////////////////////////////////////////////////////////////////////////////////////////////////////
// Super Commutative Algabra extension by Motsak
////////////////////////////////////////////////////////////////////////////////////////////////////
inline ring AssureCurrentRing(ring r)
{
ring save = currRing;
if( currRing != r )
rChangeCurrRing(r);
return save;
}
// returns the sign of: lm(pMonomM) * lm(pMonomMM),
// preserves input, may return +/-1, 0
inline int sca_Sign_mm_Mult_mm( const poly pMonomM, const poly pMonomMM, const ring rRing )
{
#ifdef PDEBUG
p_Test(pMonomM, rRing);
p_Test(pMonomMM, rRing);
#endif
const unsigned int iFirstAltVar = scaFirstAltVar(rRing);
const unsigned int iLastAltVar = scaLastAltVar(rRing);
unsigned int tpower = 0;
unsigned int cpower = 0;
for( unsigned int j = iLastAltVar; j >= iFirstAltVar; j-- )
{
const unsigned int iExpM = p_GetExp(pMonomM, j, rRing);
const unsigned int iExpMM = p_GetExp(pMonomMM, j, rRing);
#ifdef PDEBUG
assume( iExpM <= 1);
assume( iExpMM <= 1);
#endif
if( iExpMM != 0 )
{
if( iExpM != 0 )
{
return 0; // lm(pMonomM) * lm(pMonomMM) == 0
}
tpower ^= cpower; // compute degree of (-1).
}
cpower ^= iExpM;
}
#ifdef PDEBUG
assume(tpower <= 1);
#endif
// 1 => -1 // degree is odd => negate coeff.
// 0 => 1
return(1 - (tpower << 1) );
}
// returns and changes pMonomM: lt(pMonomM) = lt(pMonomM) * lt(pMonomMM),
// preserves pMonomMM. may return NULL!
// if result != NULL => next(result) = next(pMonomM), lt(result) = lt(pMonomM) * lt(pMonomMM)
// if result == NULL => pMonomM MUST BE deleted manually!
inline poly sca_m_Mult_mm( poly pMonomM, const poly pMonomMM, const ring rRing )
{
#ifdef PDEBUG
p_Test(pMonomM, rRing);
p_Test(pMonomMM, rRing);
#endif
const unsigned int iFirstAltVar = scaFirstAltVar(rRing);
const unsigned int iLastAltVar = scaLastAltVar(rRing);
unsigned int tpower = 0;
unsigned int cpower = 0;
for( unsigned int j = iLastAltVar; j >= iFirstAltVar; j-- )
{
const unsigned int iExpM = p_GetExp(pMonomM, j, rRing);
const unsigned int iExpMM = p_GetExp(pMonomMM, j, rRing);
#ifdef PDEBUG
assume( iExpM <= 1);
assume( iExpMM <= 1);
#endif
if( iExpMM != 0 )
{
if( iExpM != 0 ) // result is zero!
{
return NULL; // we do nothing with pMonomM in this case!
}
tpower ^= cpower; // compute degree of (-1).
}
cpower ^= iExpM;
}
#ifdef PDEBUG
assume(tpower <= 1);
#endif
p_ExpVectorAdd(pMonomM, pMonomMM, rRing); // "exponents" are additive!!!
number nCoeffM = p_GetCoeff(pMonomM, rRing); // no new copy! should be deleted!
if( (tpower) != 0 ) // degree is odd => negate coeff.
nCoeffM = n_Neg(nCoeffM, rRing); // negate nCoeff (will destroy the original number)
const number nCoeffMM = p_GetCoeff(pMonomMM, rRing); // no new copy!
number nCoeff = n_Mult(nCoeffM, nCoeffMM, rRing); // new number!
p_SetCoeff(pMonomM, nCoeff, rRing); // delete lc(pMonomM) and set lc(pMonomM) = nCoeff
#ifdef PDEBUG
p_Test(pMonomM, rRing);
#endif
return(pMonomM);
}
// returns and changes pMonomM: lt(pMonomM) = lt(pMonomMM) * lt(pMonomM),
// preserves pMonomMM. may return NULL!
// if result != NULL => next(result) = next(pMonomM), lt(result) = lt(pMonomMM) * lt(pMonomM)
// if result == NULL => pMonomM MUST BE deleted manually!
inline poly sca_mm_Mult_m( const poly pMonomMM, poly pMonomM, const ring rRing )
{
#ifdef PDEBUG
p_Test(pMonomM, rRing);
p_Test(pMonomMM, rRing);
#endif
const unsigned int iFirstAltVar = scaFirstAltVar(rRing);
const unsigned int iLastAltVar = scaLastAltVar(rRing);
unsigned int tpower = 0;
unsigned int cpower = 0;
for( unsigned int j = iLastAltVar; j >= iFirstAltVar; j-- )
{
const unsigned int iExpMM = p_GetExp(pMonomMM, j, rRing);
const unsigned int iExpM = p_GetExp(pMonomM, j, rRing);
#ifdef PDEBUG
assume( iExpM <= 1);
assume( iExpMM <= 1);
#endif
if( iExpM != 0 )
{
if( iExpMM != 0 ) // result is zero!
{
return NULL; // we do nothing with pMonomM in this case!
}
tpower ^= cpower; // compute degree of (-1).
}
cpower ^= iExpMM;
}
#ifdef PDEBUG
assume(tpower <= 1);
#endif
p_ExpVectorAdd(pMonomM, pMonomMM, rRing); // "exponents" are additive!!!
number nCoeffM = p_GetCoeff(pMonomM, rRing); // no new copy! should be deleted!
if( (tpower) != 0 ) // degree is odd => negate coeff.
nCoeffM = n_Neg(nCoeffM, rRing); // negate nCoeff (will destroy the original number), creates new number!
const number nCoeffMM = p_GetCoeff(pMonomMM, rRing); // no new copy!
number nCoeff = n_Mult(nCoeffM, nCoeffMM, rRing); // new number!
p_SetCoeff(pMonomM, nCoeff, rRing); // delete lc(pMonomM) and set lc(pMonomM) = nCoeff
#ifdef PDEBUG
p_Test(pMonomM, rRing);
#endif
return(pMonomM);
}
// returns: result = lt(pMonom1) * lt(pMonom2),
// preserves pMonom1, pMonom2. may return NULL!
// if result != NULL => next(result) = NULL, lt(result) = lt(pMonom1) * lt(pMonom2)
inline poly sca_mm_Mult_mm( poly pMonom1, const poly pMonom2, const ring rRing )
{
#ifdef PDEBUG
p_Test(pMonom1, rRing);
p_Test(pMonom2, rRing);
#endif
const unsigned int iFirstAltVar = scaFirstAltVar(rRing);
const unsigned int iLastAltVar = scaLastAltVar(rRing);
unsigned int tpower = 0;
unsigned int cpower = 0;
for( unsigned int j = iLastAltVar; j >= iFirstAltVar; j-- )
{
const unsigned int iExp1 = p_GetExp(pMonom1, j, rRing);
const unsigned int iExp2 = p_GetExp(pMonom2, j, rRing);
#ifdef PDEBUG
assume( iExp1 <= 1);
assume( iExp2 <= 1);
#endif
if( iExp2 != 0 )
{
if( iExp1 != 0 ) // result is zero!
{
return NULL;
}
tpower ^= cpower; // compute degree of (-1).
}
cpower ^= iExp1;
}
#ifdef PDEBUG
assume(cpower <= 1);
#endif
poly pResult;
omTypeAllocBin(poly, pResult, rRing->PolyBin);
p_SetRingOfLm(pResult, rRing);
p_ExpVectorSum(pResult, pMonom1, pMonom2, rRing); // "exponents" are additive!!!
pNext(pResult) = NULL;
const number nCoeff1 = p_GetCoeff(pMonom1, rRing); // no new copy!
const number nCoeff2 = p_GetCoeff(pMonom2, rRing); // no new copy!
number nCoeff = n_Mult(nCoeff1, nCoeff2, rRing); // new number!
if( (tpower) != 0 ) // degree is odd => negate coeff.
nCoeff = n_Neg(nCoeff, rRing); // negate nCoeff (will destroy the original number)
p_SetCoeff0(pResult, nCoeff, rRing); // set lc(pResult) = nCoeff, no destruction!
#ifdef PDEBUG
p_Test(pResult, rRing);
#endif
return(pResult);
}
// returns: result = x_i * lt(pMonom),
// preserves pMonom. may return NULL!
// if result != NULL => next(result) = NULL, lt(result) = x_i * lt(pMonom)
inline poly sca_xi_Mult_mm(unsigned int i, const poly pMonom, const ring rRing)
{
#ifdef PDEBUG
p_Test(pMonom, rRing);
#endif
assume( i <= scaLastAltVar(rRing));
assume( scaFirstAltVar(rRing) <= i );
if( p_GetExp(pMonom, i, rRing) != 0 ) // => result is zero!
return NULL;
const unsigned int iFirstAltVar = scaFirstAltVar(rRing);
unsigned int cpower = 0;
for( unsigned int j = iFirstAltVar; j < i ; j++ )
cpower ^= p_GetExp(pMonom, j, rRing);
#ifdef PDEBUG
assume(cpower <= 1);
#endif
poly pResult = p_LmInit(pMonom, rRing);
p_SetExp(pResult, i, 1, rRing); // pResult*=X_i &&
p_Setm(pResult, rRing); // addjust degree after previous step!
number nCoeff = n_Copy(p_GetCoeff(pMonom, rRing), rRing); // new number!
if( cpower != 0 ) // degree is odd => negate coeff.
nCoeff = n_Neg(nCoeff, rRing); // negate nCoeff (will destroy the original number)
p_SetCoeff0(pResult, nCoeff, rRing); // set lc(pResult) = nCoeff, no destruction!
#ifdef PDEBUG
p_Test(pResult, rRing);
#endif
return(pResult);
}
//-----------------------------------------------------------------------------------//
// return poly = pPoly * pMonom; preserve pMonom, destroy or reuse pPoly.
poly sca_p_Mult_mm(poly pPoly, const poly pMonom, const ring rRing)
{
assume( rIsSCA(rRing) );
#ifdef PDEBUG
// Print("sca_p_Mult_mm\n"); // !
p_Test(pPoly, rRing);
p_Test(pMonom, rRing);
#endif
if( pPoly == NULL )
return NULL;
if( pMonom == NULL )
{
// pPoly != NULL =>
p_Delete( &pPoly, rRing );
return NULL;
}
const int iComponentMonomM = p_GetComp(pMonom, rRing);
poly p = pPoly; poly* ppPrev = &pPoly;
loop
{
#ifdef PDEBUG
p_Test(p, rRing);
#endif
const int iComponent = p_GetComp(p, rRing);
if( iComponent!=0 )
{
if( iComponentMonomM!=0 ) // TODO: make global if on iComponentMonomM =?= 0
{
// REPORT_ERROR
Werror("sca_p_Mult_mm: exponent mismatch %d and %d\n", iComponent, iComponentMonomM);
// what should we do further?!?
p_Delete( &pPoly, rRing); // delete the result AND rest
return NULL;
}
#ifdef PDEBUG
if(iComponentMonomM==0 )
{
dReportError("sca_p_Mult_mm: Multiplication in the left module from the right");
}
#endif
}
// terms will be in the same order because of quasi-ordering!
poly v = sca_m_Mult_mm(p, pMonom, rRing);
if( v != NULL )
{
ppPrev = &pNext(p); // fixed!
// *p is changed if v != NULL ( p == v )
pIter(p);
if( p == NULL )
break;
}
else
{ // Upps! Zero!!! we must kill this term!
//
p = p_LmDeleteAndNext(p, rRing);
*ppPrev = p;
if( p == NULL )
break;
}
}
#ifdef PDEBUG
p_Test(pPoly,rRing);
#endif
return(pPoly);
}
// return new poly = pPoly * pMonom; preserve pPoly and pMonom.
poly sca_pp_Mult_mm(const poly pPoly, const poly pMonom, const ring rRing, poly &)
{
assume( rIsSCA(rRing) );
#ifdef PDEBUG
// Print("sca_pp_Mult_mm\n"); // !
p_Test(pPoly, rRing);
p_Test(pMonom, rRing);
#endif
if( ( pPoly == NULL ) || ( pMonom == NULL ) )
return NULL;
const int iComponentMonomM = p_GetComp(pMonom, rRing);
poly pResult = NULL;
poly* ppPrev = &pResult;
for( poly p = pPoly; p!= NULL; pIter(p) )
{
#ifdef PDEBUG
p_Test(p, rRing);
#endif
const int iComponent = p_GetComp(p, rRing);
if( iComponent!=0 )
{
if( iComponentMonomM!=0 ) // TODO: make global if on iComponentMonomM =?= 0
{
// REPORT_ERROR
Werror("sca_pp_Mult_mm: exponent mismatch %d and %d\n", iComponent, iComponentMonomM);
// what should we do further?!?
p_Delete( &pResult, rRing); // delete the result
return NULL;
}
#ifdef PDEBUG
if(iComponentMonomM==0 )
{
dReportError("sca_pp_Mult_mm: Multiplication in the left module from the right");
}
#endif
}
// terms will be in the same order because of quasi-ordering!
poly v = sca_mm_Mult_mm(p, pMonom, rRing);
if( v != NULL )
{
*ppPrev = v;
ppPrev = &pNext(v);
}
}
#ifdef PDEBUG
p_Test(pResult,rRing);
#endif
return(pResult);
}
//-----------------------------------------------------------------------------------//
// return x_i * pPoly; preserve pPoly.
inline poly sca_xi_Mult_pp(unsigned int i, const poly pPoly, const ring rRing)
{
assume( rIsSCA(rRing) );
#ifdef PDEBUG
p_Test(pPoly, rRing);
#endif
assume(i <= scaLastAltVar(rRing));
assume(scaFirstAltVar(rRing) <= i);
if( pPoly == NULL )
return NULL;
poly pResult = NULL;
poly* ppPrev = &pResult;
for( poly p = pPoly; p!= NULL; pIter(p) )
{
// terms will be in the same order because of quasi-ordering!
poly v = sca_xi_Mult_mm(i, p, rRing);
#ifdef PDEBUG
p_Test(v, rRing);
#endif
if( v != NULL )
{
*ppPrev = v;
ppPrev = &pNext(*ppPrev);
}
}
#ifdef PDEBUG
p_Test(pResult, rRing);
#endif
return(pResult);
}
// return new poly = pMonom * pPoly; preserve pPoly and pMonom.
poly sca_mm_Mult_pp(const poly pMonom, const poly pPoly, const ring rRing)
{
assume( rIsSCA(rRing) );
#ifdef PDEBUG
// Print("sca_mm_Mult_pp\n"); // !
p_Test(pPoly, rRing);
p_Test(pMonom, rRing);
#endif
if( ( pPoly == NULL ) || ( pMonom == NULL ) )
return NULL;
const int iComponentMonomM = p_GetComp(pMonom, rRing);
poly pResult = NULL;
poly* ppPrev = &pResult;
for( poly p = pPoly; p!= NULL; pIter(p) )
{
#ifdef PDEBUG
p_Test(p, rRing);
#endif
const int iComponent = p_GetComp(p, rRing);
if( iComponentMonomM!=0 )
{
if( iComponent!=0 ) // TODO: make global if on iComponentMonomM =?= 0
{
// REPORT_ERROR
Werror("sca_mm_Mult_pp: exponent mismatch %d and %d\n", iComponent, iComponentMonomM);
// what should we do further?!?
p_Delete( &pResult, rRing); // delete the result
return NULL;
}
#ifdef PDEBUG
if(iComponent==0 )
{
dReportError("sca_mm_Mult_pp: Multiplication in the left module from the right!");
// PrintS("mm = "); p_Write(pMonom, rRing);
// PrintS("pp = "); p_Write(pPoly, rRing);
// assume(iComponent!=0);
}
#endif
}
// terms will be in the same order because of quasi-ordering!
poly v = sca_mm_Mult_mm(pMonom, p, rRing);
if( v != NULL )
{
*ppPrev = v;
ppPrev = &pNext(*ppPrev); // nice line ;-)
}
}
#ifdef PDEBUG
p_Test(pResult,rRing);
#endif
return(pResult);
}
// return poly = pMonom * pPoly; preserve pMonom, destroy or reuse pPoly.
poly sca_mm_Mult_p(const poly pMonom, poly pPoly, const ring rRing) // !!!!! the MOST used procedure !!!!!
{
assume( rIsSCA(rRing) );
#ifdef PDEBUG
p_Test(pPoly, rRing);
p_Test(pMonom, rRing);
#endif
if( pPoly == NULL )
return NULL;
if( pMonom == NULL )
{
// pPoly != NULL =>
p_Delete( &pPoly, rRing );
return NULL;
}
const int iComponentMonomM = p_GetComp(pMonom, rRing);
poly p = pPoly; poly* ppPrev = &pPoly;
loop
{
#ifdef PDEBUG
if( !p_Test(p, rRing) )
{
PrintS("p is wrong!");
p_Write(p,rRing);
}
#endif
const int iComponent = p_GetComp(p, rRing);
if( iComponentMonomM!=0 )
{
if( iComponent!=0 )
{
// REPORT_ERROR
Werror("sca_mm_Mult_p: exponent mismatch %d and %d\n", iComponent, iComponentMonomM);
// what should we do further?!?
p_Delete( &pPoly, rRing); // delete the result
return NULL;
}
#ifdef PDEBUG
if(iComponent==0)
{
dReportError("sca_mm_Mult_p: Multiplication in the left module from the right!");
// PrintS("mm = "); p_Write(pMonom, rRing);
// PrintS("p = "); p_Write(pPoly, rRing);
// assume(iComponent!=0);
}
#endif
}
// terms will be in the same order because of quasi-ordering!
poly v = sca_mm_Mult_m(pMonom, p, rRing);
if( v != NULL )
{
ppPrev = &pNext(p);
// *p is changed if v != NULL ( p == v )
pIter(p);
if( p == NULL )
break;
}
else
{ // Upps! Zero!!! we must kill this term!
p = p_LmDeleteAndNext(p, rRing);
*ppPrev = p;
if( p == NULL )
break;
}
}
#ifdef PDEBUG
if( !p_Test(pPoly, rRing) )
{
PrintS("pPoly is wrong!");
p_Write(pPoly, rRing);
}
#endif
return(pPoly);
}
//-----------------------------------------------------------------------------------//
#ifdef PDEBUG
#endif
//-----------------------------------------------------------------------------------//
// GB computation routines:
/*4
* creates the S-polynomial of p1 and p2
* does not destroy p1 and p2
*/
poly sca_SPoly( const poly p1, const poly p2, const ring r )
{
assume( rIsSCA(r) );
const long lCompP1 = p_GetComp(p1,r);
const long lCompP2 = p_GetComp(p2,r);
if ((lCompP1!=lCompP2) && (lCompP1!=0) && (lCompP2!=0))
{
#ifdef PDEBUG
dReportError("sca_SPoly: different non-zero components!\n");
#endif
return(NULL);
}
poly pL = p_Lcm(p1, p2, si_max(lCompP1, lCompP2), r); // pL = lcm( lm(p1), lm(p2) )
poly m1 = p_One( r);
p_ExpVectorDiff(m1, pL, p1, r); // m1 = pL / lm(p1)
//p_SetComp(m1,0,r);
//p_Setm(m1,r);
#ifdef PDEBUG
p_Test(m1,r);
#endif
poly m2 = p_One( r);
p_ExpVectorDiff (m2, pL, p2, r); // m2 = pL / lm(p2)
//p_SetComp(m2,0,r);
//p_Setm(m2,r);
#ifdef PDEBUG
p_Test(m2,r);
#endif
p_Delete(&pL,r);
number C1 = n_Copy(p_GetCoeff(p1,r),r); // C1 = lc(p1)
number C2 = n_Copy(p_GetCoeff(p2,r),r); // C2 = lc(p2)
number C = nGcd(C1,C2,r); // C = gcd(C1, C2)
if (!n_IsOne(C, r)) // if C != 1
{
C1=n_Div(C1, C, r); // C1 = C1 / C
C2=n_Div(C2, C, r); // C2 = C2 / C
}
n_Delete(&C,r); // destroy the number C
const int iSignSum = sca_Sign_mm_Mult_mm (m1, p1, r) + sca_Sign_mm_Mult_mm (m2, p2, r);
// zero if different signs
assume( (iSignSum*iSignSum == 0) || (iSignSum*iSignSum == 4) );
if( iSignSum != 0 ) // the same sign!
C2=n_Neg (C2, r);
p_SetCoeff(m1, C2, r); // lc(m1) = C2!!!
p_SetCoeff(m2, C1, r); // lc(m2) = C1!!!
poly tmp1 = nc_mm_Mult_pp (m1, pNext(p1), r); // tmp1 = m1 * tail(p1),
p_Delete(&m1,r); // => n_Delete(&C1,r);
poly tmp2 = nc_mm_Mult_pp (m2, pNext(p2), r); // tmp1 = m2 * tail(p2),
p_Delete(&m2,r); // => n_Delete(&C1,r);
poly spoly = p_Add_q (tmp1, tmp2, r); // spoly = spoly(lt(p1), lt(p2)) + m1 * tail(p1), delete tmp1,2
if (spoly!=NULL) pCleardenom (spoly); // r?
// if (spoly!=NULL) pContent (spoly); // r?
#ifdef PDEBUG
p_Test (spoly, r);
#endif
return(spoly);
}
/*2
* reduction of p2 with p1
* do not destroy p1, but p2
* p1 divides p2 -> for use in NF algorithm
*/
poly sca_ReduceSpoly(const poly p1, poly p2, const ring r)
{
assume( rIsSCA(r) );
assume( p1 != NULL );
const long lCompP1 = p_GetComp (p1, r);
const long lCompP2 = p_GetComp (p2, r);
if ((lCompP1!=lCompP2) && (lCompP1!=0) && (lCompP2!=0))
{
#ifdef PDEBUG
dReportError("sca_ReduceSpoly: different non-zero components!");
#endif
return(NULL);
}
poly m = p_ISet (1, r);
p_ExpVectorDiff (m, p2, p1, r); // m = lm(p2) / lm(p1)
//p_Setm(m,r);
#ifdef PDEBUG
p_Test (m,r);
#endif
number C1 = n_Copy( p_GetCoeff(p1, r), r);
number C2 = n_Copy( p_GetCoeff(p2, r), r);
/* GCD stuff */
number C = nGcd(C1, C2, r);
if (!n_IsOne(C, r))
{
C1 = n_Div(C1, C, r);
C2 = n_Div(C2, C, r);
}
n_Delete(&C,r);
const int iSign = sca_Sign_mm_Mult_mm( m, p1, r );
if(iSign == 1)
C2 = n_Neg(C2,r);
p_SetCoeff(m, C2, r);
#ifdef PDEBUG
p_Test(m,r);
#endif
p2 = p_LmDeleteAndNext( p2, r );
p2 = p_Mult_nn(p2, C1, r); // p2 !!!
n_Delete(&C1,r);
poly T = nc_mm_Mult_pp(m, pNext(p1), r);
p_Delete(&m, r);
p2 = p_Add_q(p2, T, r);
if ( p2!=NULL ) pContent(p2); // r?
#ifdef PDEBUG
p_Test(p2,r);
#endif
return(p2);
}
void addLObject(LObject& h, kStrategy& strat)
{
if(h.IsNull()) return;
strat->initEcart(&h);
h.sev=0; // pGetShortExpVector(h.p);
// add h into S and L
int pos=posInS(strat, strat->sl, h.p, h.ecart);
if ( (pos <= strat->sl) && (pComparePolys(h.p, strat->S[pos])) )
{
if (TEST_OPT_PROT)
PrintS("d\n");
}
else
{
if (TEST_OPT_INTSTRATEGY)
{
pCleardenom(h.p);
}
else
{
pNorm(h.p);
pContent(h.p);
}
if ((strat->syzComp==0)||(!strat->homog))
{
h.p = redtailBba(h.p,pos-1,strat);
if (TEST_OPT_INTSTRATEGY)
{
// pCleardenom(h.p);
pContent(h.p);
}
else
{
pNorm(h.p);
}
}
if(h.IsNull()) return;
/* statistic */
if (TEST_OPT_PROT)
{
PrintS("s\n");
}
#ifdef KDEBUG
if (TEST_OPT_DEBUG)
{
PrintS("new s:");
wrp(h.p);
PrintLn();
}
#endif
enterpairs(h.p, strat->sl, h.ecart, 0, strat);
pos=0;
if (strat->sl!=-1) pos = posInS(strat, strat->sl, h.p, h.ecart);
strat->enterS(h, pos, strat, -1);
// enterT(h, strat); // ?!
if (h.lcm!=NULL) pLmFree(h.lcm);
}
}
ideal sca_gr_bba(const ideal F, const ideal Q, const intvec *, const intvec *, kStrategy strat)
{
#if MYTEST
PrintS("\n");
#endif
assume(rIsSCA(currRing));
#ifndef NDEBUG
idTest(F);
idTest(Q);
#endif
#ifdef HAVE_PLURAL
#if MYTEST
PrintS("currRing: \n");
rWrite(currRing);
#ifdef RDEBUG
rDebugPrint(currRing);
#endif
PrintS("F: \n");
idPrint(F);
PrintS("Q: \n");
idPrint(Q);
#endif
#endif
const unsigned int m_iFirstAltVar = scaFirstAltVar(currRing);
const unsigned int m_iLastAltVar = scaLastAltVar(currRing);
ideal tempF = id_KillSquares(F, m_iFirstAltVar, m_iLastAltVar, currRing);
ideal tempQ = Q;
if(Q == currQuotient)
tempQ = SCAQuotient(currRing);
strat->z2homog = id_IsSCAHomogeneous(tempF, NULL, NULL, currRing); // wCx == wCy == NULL!
// redo: no_prod_crit
const BOOLEAN bIsSCA = rIsSCA(currRing) && strat->z2homog; // for Z_2 prod-crit
strat->no_prod_crit = ! bIsSCA;
// strat->homog = strat->homog && strat->z2homog; // ?
#if MYTEST
{
PrintS("ideal tempF: \n");
idPrint(tempF);
PrintS("ideal tempQ: \n");
idPrint(tempQ);
}
#endif
#ifdef KDEBUG
om_Opts.MinTrack = 5;
#endif
int srmax, lrmax;
int olddeg, reduc;
int red_result = 1;
// int hilbeledeg = 1, minimcnt = 0;
int hilbcount = 0;
initBuchMoraCrit(strat); // set Gebauer, honey, sugarCrit
nc_gr_initBba(tempF,strat); // set enterS, red, initEcart, initEcartPair
initBuchMoraPos(strat);
// ?? set spSpolyShort, reduce ???
initBuchMora(tempF, tempQ, strat); // SCAQuotient(currRing) instead of Q == squares!!!!!!!
strat->posInT=posInT110; // !!!
srmax = strat->sl;
reduc = olddeg = lrmax = 0;
/* compute------------------------------------------------------- */
for(; strat->Ll >= 0;
#ifdef KDEBUG
strat->P.lcm = NULL,
#endif
kTest(strat)
)
{
if (strat->Ll > lrmax) lrmax =strat->Ll;/*stat.*/
#ifdef KDEBUG
if (TEST_OPT_DEBUG) messageSets(strat);
#endif
if (strat->Ll== 0) strat->interpt=TRUE;
if (TEST_OPT_DEGBOUND
&& ((strat->honey
&& (strat->L[strat->Ll].ecart+pFDeg(strat->L[strat->Ll].p,currRing)>Kstd1_deg))
|| ((!strat->honey) && (pFDeg(strat->L[strat->Ll].p,currRing)>Kstd1_deg))))
{
/*
*stops computation if
* 24 IN test and the degree +ecart of L[strat->Ll] is bigger then
*a predefined number Kstd1_deg
*/
while (strat->Ll >= 0) deleteInL(strat->L,&strat->Ll,strat->Ll,strat);
break;
}
/* picks the last element from the lazyset L */
strat->P = strat->L[strat->Ll];
strat->Ll--;
//kTest(strat);
// assume(pNext(strat->P.p) != strat->tail); // !???
if(strat->P.IsNull()) continue;
if( pNext(strat->P.p) == strat->tail )
{
// deletes the int spoly and computes SPoly
pLmFree(strat->P.p); // ???
strat->P.p = nc_CreateSpoly(strat->P.p1, strat->P.p2, currRing);
}
if(strat->P.IsNull()) continue;
// poly save = NULL;
//
// if(pNext(strat->P.p) != NULL)
// save = p_Copy(strat->P.p, currRing);
strat->initEcart(&strat->P); // remove it?
if (TEST_OPT_PROT)
message((strat->honey ? strat->P.ecart : 0) + strat->P.pFDeg(), &olddeg,&reduc,strat, red_result);
// reduction of the element chosen from L wrt S
strat->red(&strat->P,strat);
if(strat->P.IsNull()) continue;
addLObject(strat->P, strat);
if (strat->sl > srmax) srmax = strat->sl;
const poly save = strat->P.p;
#ifdef PDEBUG
p_Test(save, currRing);
#endif
assume( save != NULL );
// SCA Specials:
{
const poly p_next = pNext(save);
if( p_next != NULL )
for( unsigned int i = m_iFirstAltVar; i <= m_iLastAltVar; i++ )
if( p_GetExp(save, i, currRing) != 0 )
{
assume(p_GetExp(save, i, currRing) == 1);
const poly tt = sca_pp_Mult_xi_pp(i, p_next, currRing);
#ifdef PDEBUG
p_Test(tt, currRing);
#endif
if( tt == NULL) continue;
LObject h(tt); // h = x_i * P
if (TEST_OPT_INTSTRATEGY)
{
// h.pCleardenom(); // also does a pContent
pContent(h.p);
}
else
{
h.pNorm();
}
strat->initEcart(&h);
// if (pOrdSgn==-1)
// {
// cancelunit(&h); // tries to cancel a unit
// deleteHC(&h, strat);
// }
// if(h.IsNull()) continue;
// if (TEST_OPT_PROT)
// message((strat->honey ? h.ecart : 0) + h.pFDeg(), &olddeg, &reduc, strat, red_result);
// strat->red(&h, strat); // wrt S
// if(h.IsNull()) continue;
// poly save = p_Copy(h.p, currRing);
int pos;
if (strat->Ll==-1)
pos =0;
else
pos = strat->posInL(strat->L,strat->Ll,&h,strat);
h.sev = pGetShortExpVector(h.p);
enterL(&strat->L,&strat->Ll,&strat->Lmax,h,pos);
// h.p = save;
// addLObject(h, strat);
// if (strat->sl > srmax) srmax = strat->sl;
}
// p_Delete( &save, currRing );
}
} // for(;;)
#ifdef KDEBUG
if (TEST_OPT_DEBUG) messageSets(strat);
#endif
if (TEST_OPT_REDSB){
completeReduce(strat); // ???
}
/* release temp data-------------------------------- */
exitBuchMora(strat);
if (TEST_OPT_WEIGHTM)
{
pFDeg=pFDegOld;
pLDeg=pLDegOld;
if (ecartWeights)
{
omFreeSize((ADDRESS)ecartWeights,(pVariables+1)*sizeof(int));
ecartWeights=NULL;
}
}
if (TEST_OPT_PROT) messageStat(srmax,lrmax,hilbcount,strat);
if (tempQ!=NULL) updateResult(strat->Shdl,tempQ,strat);
id_Delete(&tempF, currRing);
/* complete reduction of the standard basis--------- */
if (TEST_OPT_REDSB){
ideal I = strat->Shdl;
ideal erg = kInterRedOld(I,tempQ);
assume(I!=erg);
id_Delete(&I, currRing);
strat->Shdl = erg;
}
#if MYTEST
// PrintS("\n");
#endif
return (strat->Shdl);
}
// should be used only inside nc_SetupQuotient!
// Check whether this our case:
// 1. rG is a commutative polynomial ring \otimes anticommutative algebra
// 2. factor ideal rGR->qideal contains squares of all alternating variables.
//
// if yes, make rGR a super-commutative algebra!
// NOTE: Factors of SuperCommutative Algebras are supported this way!
//
// rG == NULL means that there is no separate base G-algebra in this case take rGR == rG
// special case: bCopy == true (default value: false)
// meaning: rGR copies structure from rG
// (maybe with some minor changes, which don't change the type!)
bool sca_SetupQuotient(ring rGR, ring rG, bool bCopy)
{
//////////////////////////////////////////////////////////////////////////
// checks...
//////////////////////////////////////////////////////////////////////////
if( rG == NULL )
rG = rGR;
assume(rGR != NULL);
assume(rG != NULL);
assume(rIsPluralRing(rG));
#if MYTEST
PrintS("sca_SetupQuotient(rGR, rG, bCopy)");
{
ring rSaveRing = AssureCurrentRing(rG);
PrintS("\nrG: \n"); rWrite(rG);
AssureCurrentRing(rGR);
PrintS("\nrGR: \n"); rWrite(rGR);
PrintLn();
AssureCurrentRing(rSaveRing);
}
#endif
if(bCopy)
{
if(rIsSCA(rG) && (rG != rGR))
return sca_Force(rGR, scaFirstAltVar(rG), scaLastAltVar(rG));
else
return false;
}
assume(!bCopy);
const int N = rG->N;
if(N < 2)
return false;
// if( (ncRingType(rG) != nc_skew) || (ncRingType(rG) != nc_comm) )
// return false;
#if OUTPUT
PrintS("sca_SetupQuotient: qring?\n");
#endif
if(rGR->qideal == NULL) // there should be a factor!
return false;
#if OUTPUT
PrintS("sca_SetupQuotient: qideal!!!\n");
#endif
// if((rG->qideal != NULL) && (rG != rGR) ) // we cannot change from factor to factor at the time, sorry!
// return false;
int iAltVarEnd = -1;
int iAltVarStart = N+1;
const ring rBase = rG->GetNC()->basering;
const matrix C = rG->GetNC()->C; // live in rBase!
#if OUTPUT
PrintS("sca_SetupQuotient: AltVars?!\n");
#endif
for(int i = 1; i < N; i++)
{
for(int j = i + 1; j <= N; j++)
{
assume(MATELEM(C,i,j) != NULL); // after CallPlural!
number c = p_GetCoeff(MATELEM(C,i,j), rBase);
if( n_IsMOne(c, rBase) ) // !!!???
{
if( i < iAltVarStart)
iAltVarStart = i;
if( j > iAltVarEnd)
iAltVarEnd = j;
} else
{
if( !n_IsOne(c, rBase) )
{
#if OUTPUT
Print("Wrong Coeff at: [%d, %d]\n", i, j);
#endif
#if MYTEST
Print("Wrong Coeff at: [%d, %d]\n", i, j);
#endif
return false;
}
}
}
}
#if MYTEST
Print("AltVars?1: [%d, %d]\n", iAltVarStart, iAltVarEnd);
#endif
if( (iAltVarEnd == -1) || (iAltVarStart == (N+1)) )
return false; // either no alternating varables, or a single one => we are in commutative case!
for(int i = 1; i < N; i++)
{
for(int j = i + 1; j <= N; j++)
{
assume(MATELEM(C,i,j) != NULL); // after CallPlural!
number c = p_GetCoeff(MATELEM(C,i,j), rBase);
if( (iAltVarStart <= i) && (j <= iAltVarEnd) ) // S <= i < j <= E
{ // anticommutative part
if( !n_IsMOne(c, rBase) )
{
#ifdef PDEBUG
#if OUTPUT
Print("Wrong Coeff at: [%d, %d]\n", i, j);
#endif
#endif
#if MYTEST
Print("Wrong Coeff at: [%d, %d]\n", i, j);
#endif
return false;
}
} else
{ // should commute
if( !n_IsOne(c, rBase) )
{
#ifdef PDEBUG
#if OUTPUT
Print("Wrong Coeff at: [%d, %d]\n", i, j);
#endif
#endif
#if MYTEST
Print("Wrong Coeff at: [%d, %d]\n", i, j);
#endif
return false;
}
}
}
}
#if MYTEST
Print("AltVars!?: [%d, %d]\n", iAltVarStart, iAltVarEnd);
#endif
assume( 1 <= iAltVarStart );
assume( iAltVarStart < iAltVarEnd );
assume( iAltVarEnd <= N );
ring rSaveRing = AssureCurrentRing(rG);
assume(rGR->qideal != NULL);
assume(rGR->N == rG->N);
// assume(rG->qideal == NULL); // ?
const ideal idQuotient = rGR->qideal;
#if MYTEST
PrintS("Analyzing quotient ideal:\n");
idPrint(idQuotient); // in rG!!!
#endif
// check for
// y_{iAltVarStart}^2, y_{iAltVarStart+1}^2, \ldots, y_{iAltVarEnd}^2 (iAltVarEnd > iAltVarStart)
// to be within quotient ideal.
bool bSCA = true;
int b = 1;
int e = N;
if(rIsSCA(rG))
{
b = si_max(b, scaFirstAltVar(rG));
e = si_min(e, scaLastAltVar(rG));
#if MYTEST
Print("AltVars!?: [%d, %d]\n", b, e);
#endif
}
for ( int i = iAltVarStart; (i <= iAltVarEnd) && bSCA; i++ )
if( (i < b) || (i > e) ) // otherwise it's ok since rG is an SCA!
{
poly square = p_One( rG);
p_SetExp(square, i, 2, rG); // square = var(i)^2.
p_Setm(square, rG);
// square = NF( var(i)^2 | Q )
// NOTE: rSaveRing == currRing now!
// NOTE: there is no better way to check this in general!
square = kNF(idQuotient, NULL, square, 0, 1); // must ran in currRing == rG!
if( square != NULL ) // var(i)^2 is not in Q?
{
p_Delete(&square, rG);
bSCA = false;
break;
}
}
AssureCurrentRing(rSaveRing);
if(!bSCA) return false;
#ifdef PDEBUG
#if OUTPUT
Print("ScaVars!: [%d, %d]\n", iAltVarStart, iAltVarEnd);
#endif
#endif
//////////////////////////////////////////////////////////////////////////
// ok... here we go. let's setup it!!!
//////////////////////////////////////////////////////////////////////////
ideal tempQ = id_KillSquares(idQuotient, iAltVarStart, iAltVarEnd, rG); // in rG!!!
#ifdef PDEBUG
#if OUTPUT
PrintS("Quotient: \n");
iiWriteMatrix((matrix)idQuotient,"__",1);
PrintS("tempSCAQuotient: \n");
iiWriteMatrix((matrix)tempQ,"__",1);
#endif
#endif
idSkipZeroes( tempQ );
ncRingType( rGR, nc_exterior );
scaFirstAltVar( rGR, iAltVarStart );
scaLastAltVar( rGR, iAltVarEnd );
if( idIs0(tempQ) )
rGR->GetNC()->SCAQuotient() = NULL;
else
rGR->GetNC()->SCAQuotient() = idrMoveR(tempQ, rG, rGR); // deletes tempQ!
nc_p_ProcsSet(rGR, rGR->p_Procs); // !!!!!!!!!!!!!!!!!
#ifdef PDEBUG
#if OUTPUT
PrintS("SCAQuotient: \n");
if(tempQ != NULL)
iiWriteMatrix((matrix)tempQ,"__",1);
else
PrintS("(NULL)\n");
#endif
#endif
return true;
}
bool sca_Force(ring rGR, int b, int e)
{
assume(rGR != NULL);
assume(rIsPluralRing(rGR));
assume(!rIsSCA(rGR));
const int N = rGR->N;
ring rSaveRing = currRing;
if(rSaveRing != rGR)
rChangeCurrRing(rGR);
const ideal idQuotient = rGR->qideal;
ideal tempQ = idQuotient;
if( b <= N && e >= 1 )
tempQ = id_KillSquares(idQuotient, b, e, rGR);
idSkipZeroes( tempQ );
ncRingType( rGR, nc_exterior );
if( idIs0(tempQ) )
rGR->GetNC()->SCAQuotient() = NULL;
else
rGR->GetNC()->SCAQuotient() = tempQ;
scaFirstAltVar( rGR, b );
scaLastAltVar( rGR, e );
nc_p_ProcsSet(rGR, rGR->p_Procs);
if(rSaveRing != rGR)
rChangeCurrRing(rSaveRing);
return true;
}
// return x_i * pPoly; preserve pPoly.
poly sca_pp_Mult_xi_pp(unsigned int i, const poly pPoly, const ring rRing)
{
assume(1 <= i);
assume(i <= (unsigned int)rRing->N);
if(rIsSCA(rRing))
return sca_xi_Mult_pp(i, pPoly, rRing);
poly xi = p_One( rRing);
p_SetExp(xi, i, 1, rRing);
p_Setm(xi, rRing);
poly pResult = pp_Mult_qq(xi, pPoly, rRing);
p_Delete( &xi, rRing);
return pResult;
}
///////////////////////////////////////////////////////////////////////////////////////
//************* SCA BBA *************************************************************//
///////////////////////////////////////////////////////////////////////////////////////
// Under development!!!
ideal sca_bba (const ideal F, const ideal Q, const intvec *w, const intvec * /*hilb*/, kStrategy strat)
{
#if MYTEST
PrintS("\n\n\n\n");
#endif
assume(rIsSCA(currRing));
#ifndef NDEBUG
idTest(F);
idTest(Q);
#endif
#if MYTEST
PrintS("\ncurrRing: \n");
rWrite(currRing);
#ifdef RDEBUG
// rDebugPrint(currRing);
#endif
PrintS("\n\nF: \n");
idPrint(F);
PrintS("\n\nQ: \n");
idPrint(Q);
PrintLn();
#endif
const unsigned int m_iFirstAltVar = scaFirstAltVar(currRing);
const unsigned int m_iLastAltVar = scaLastAltVar(currRing);
ideal tempF = id_KillSquares(F, m_iFirstAltVar, m_iLastAltVar, currRing);
ideal tempQ = Q;
if(Q == currQuotient)
tempQ = SCAQuotient(currRing);
// Q or tempQ will not be used below :(((
#if MYTEST
PrintS("tempF: \n");
idPrint(tempF);
PrintS("tempQ: \n");
idPrint(tempQ);
#endif
strat->z2homog = id_IsSCAHomogeneous(tempF, NULL, NULL, currRing); // wCx == wCy == NULL!
// redo no_prod_crit:
const BOOLEAN bIsSCA = rIsSCA(currRing) && strat->z2homog; // for Z_2 prod-crit
strat->no_prod_crit = ! bIsSCA;
// strat->homog = strat->homog && strat->z2homog; // ?
#ifdef KDEBUG
om_Opts.MinTrack = 5;
#endif
int srmax, lrmax, red_result = 1;
int olddeg, reduc;
// int hilbeledeg = 1, minimcnt = 0;
int hilbcount = 0;
BOOLEAN withT = FALSE;
initBuchMoraCrit(strat); // sets Gebauer, honey, sugarCrit // sca - ok???
initBuchMoraPos(strat); // sets strat->posInL, strat->posInT // check!! (Plural's: )
// initHilbCrit(F, Q, &hilb, strat);
// nc_gr_initBba(F,strat);
initBba(tempF, strat); // set enterS, red, initEcart, initEcartPair
/*set enterS, spSpolyShort, reduce, red, initEcart, initEcartPair*/
// ?? set spSpolyShort, reduce ???
initBuchMora(tempF, tempQ, strat); // tempQ = Q - squares!!!
// if (strat->minim>0) strat->M = idInit(IDELEMS(F),F->rank);
srmax = strat->sl;
reduc = olddeg = lrmax = 0;
#define NO_BUCKETS
#ifndef NO_BUCKETS
if (!TEST_OPT_NOT_BUCKETS)
strat->use_buckets = 1;
#endif
// redtailBBa against T for inhomogenous input
if (!K_TEST_OPT_OLDSTD)
withT = ! strat->homog;
// strat->posInT = posInT_pLength;
kTest_TS(strat);
#undef HAVE_TAIL_RING
#ifdef HAVE_TAIL_RING
kStratInitChangeTailRing(strat);
#endif
///////////////////////////////////////////////////////////////
// SCA:
/* compute------------------------------------------------------- */
while (strat->Ll >= 0)
{
if (strat->Ll > lrmax) lrmax =strat->Ll;/*stat.*/
#ifdef KDEBUG
// loop_count++;
if (TEST_OPT_DEBUG) messageSets(strat);
#endif
if (strat->Ll== 0) strat->interpt=TRUE;
if (TEST_OPT_DEGBOUND
&& ((strat->honey && (strat->L[strat->Ll].ecart+pFDeg(strat->L[strat->Ll].p,currRing)>Kstd1_deg))
|| ((!strat->honey) && (pFDeg(strat->L[strat->Ll].p,currRing)>Kstd1_deg))))
{
/*
*stops computation if
* 24 IN test and the degree +ecart of L[strat->Ll] is bigger then
*a predefined number Kstd1_deg
*/
while ((strat->Ll >= 0)
&& (strat->L[strat->Ll].p1!=NULL) && (strat->L[strat->Ll].p2!=NULL)
&& ((strat->honey && (strat->L[strat->Ll].ecart+pFDeg(strat->L[strat->Ll].p,currRing)>Kstd1_deg))
|| ((!strat->honey) && (pFDeg(strat->L[strat->Ll].p,currRing)>Kstd1_deg)))
)
deleteInL(strat->L,&strat->Ll,strat->Ll,strat);
if (strat->Ll<0) break;
else strat->noClearS=TRUE;
}
/* picks the last element from the lazyset L */
strat->P = strat->L[strat->Ll];
strat->Ll--;
// assume(pNext(strat->P.p) != strat->tail);
if(strat->P.IsNull()) continue;
if (pNext(strat->P.p) == strat->tail)
{
// deletes the short spoly
pLmFree(strat->P.p);
strat->P.p = nc_CreateSpoly(strat->P.p1, strat->P.p2, currRing);
if (strat->P.p!=NULL) strat->initEcart(&strat->P);
}// else
if(strat->P.IsNull()) continue;
if (strat->P.p1 == NULL)
{
// if (strat->minim > 0)
// strat->P.p2=p_Copy(strat->P.p, currRing, strat->tailRing);
// for input polys, prepare reduction
strat->P.PrepareRed(strat->use_buckets);
}
if (TEST_OPT_PROT)
message((strat->honey ? strat->P.ecart : 0) + strat->P.pFDeg(),
&olddeg,&reduc,strat, red_result);
/* reduction of the element choosen from L */
red_result = strat->red(&strat->P,strat);
// reduction to non-zero new poly
if (red_result == 1)
{
/* statistic */
if (TEST_OPT_PROT) PrintS("s");
// get the polynomial (canonicalize bucket, make sure P.p is set)
strat->P.GetP(strat->lmBin);
int pos = posInS(strat,strat->sl,strat->P.p,strat->P.ecart);
// reduce the tail and normalize poly
if (TEST_OPT_INTSTRATEGY)
{
strat->P.pCleardenom();
if ((TEST_OPT_REDSB)||(TEST_OPT_REDTAIL))
{
strat->P.p = redtailBba(&(strat->P),pos-1,strat, withT); // !!!
strat->P.pCleardenom();
}
}
else
{
strat->P.pNorm();
if ((TEST_OPT_REDSB)||(TEST_OPT_REDTAIL))
strat->P.p = redtailBba(&(strat->P),pos-1,strat, withT);
}
strat->P.is_normalized=nIsOne(pGetCoeff(strat->P.p));
#ifdef KDEBUG
if (TEST_OPT_DEBUG){PrintS(" ns:");p_wrp(strat->P.p,currRing);PrintLn();}
#endif
// // min_std stuff
// if ((strat->P.p1==NULL) && (strat->minim>0))
// {
// if (strat->minim==1)
// {
// strat->M->m[minimcnt]=p_Copy(strat->P.p,currRing,strat->tailRing);
// p_Delete(&strat->P.p2, currRing, strat->tailRing);
// }
// else
// {
// strat->M->m[minimcnt]=strat->P.p2;
// strat->P.p2=NULL;
// }
// if (strat->tailRing!=currRing && pNext(strat->M->m[minimcnt])!=NULL)
// pNext(strat->M->m[minimcnt])
// = strat->p_shallow_copy_delete(pNext(strat->M->m[minimcnt]),
// strat->tailRing, currRing,
// currRing->PolyBin);
// minimcnt++;
// }
// enter into S, L, and T
//if(withT)
enterT(strat->P, strat);
// L
enterpairs(strat->P.p,strat->sl,strat->P.ecart,pos,strat, strat->tl);
// posInS only depends on the leading term
strat->enterS(strat->P, pos, strat, strat->tl);
// if (hilb!=NULL) khCheck(Q,w,hilb,hilbeledeg,hilbcount,strat);
// Print("[%d]",hilbeledeg);
if (strat->P.lcm!=NULL) pLmFree(strat->P.lcm);
if (strat->sl>srmax) srmax = strat->sl;
// //////////////////////////////////////////////////////////
// SCA:
const poly pSave = strat->P.p;
const poly p_next = pNext(pSave);
// if(0)
if( p_next != NULL )
for( unsigned int i = m_iFirstAltVar; i <= m_iLastAltVar; i++ )
if( p_GetExp(pSave, i, currRing) != 0 )
{
assume(p_GetExp(pSave, i, currRing) == 1);
const poly p_new = sca_pp_Mult_xi_pp(i, p_next, currRing);
#ifdef PDEBUG
p_Test(p_new, currRing);
#endif
if( p_new == NULL) continue;
LObject h(p_new); // h = x_i * strat->P
if (TEST_OPT_INTSTRATEGY)
{
pContent(h.p);
}
else
{
h.pNorm();
}
strat->initEcart(&h);
h.sev = pGetShortExpVector(h.p);
int pos;
if (strat->Ll==-1)
pos =0;
else
pos = strat->posInL(strat->L,strat->Ll,&h,strat);
enterL(&strat->L,&strat->Ll,&strat->Lmax,h,pos);
/*
h.sev = pGetShortExpVector(h.p);
strat->initEcart(&h);
h.PrepareRed(strat->use_buckets);
// reduction of the element choosen from L(?)
red_result = strat->red(&h,strat);
// reduction to non-zero new poly
if (red_result != 1) continue;
int pos = posInS(strat,strat->sl,h.p,h.ecart);
// reduce the tail and normalize poly
if (TEST_OPT_INTSTRATEGY)
{
h.pCleardenom();
if ((TEST_OPT_REDSB)||(TEST_OPT_REDTAIL))
{
h.p = redtailBba(&(h),pos-1,strat, withT); // !!!
h.pCleardenom();
}
}
else
{
h.pNorm();
if ((TEST_OPT_REDSB)||(TEST_OPT_REDTAIL))
h.p = redtailBba(&(h),pos-1,strat, withT);
}
#ifdef KDEBUG
if (TEST_OPT_DEBUG){PrintS(" N:");h.wrp();PrintLn();}
#endif
// h.PrepareRed(strat->use_buckets); // ???
h.sev = pGetShortExpVector(h.p);
strat->initEcart(&h);
if (strat->Ll==-1)
pos = 0;
else
pos = strat->posInL(strat->L,strat->Ll,&h,strat);
enterL(&strat->L,&strat->Ll,&strat->Lmax,h,pos);*/
} // for all x_i \in Ann(lm(P))
} // if red(P) != NULL
// else if (strat->P.p1 == NULL && strat->minim > 0)
// {
// p_Delete(&strat->P.p2, currRing, strat->tailRing);
// }
#ifdef KDEBUG
// memset(&(strat->P), 0, sizeof(strat->P));
#endif
kTest_TS(strat); // even of T is not used!
// Print("\n$\n");
}
#ifdef KDEBUG
if (TEST_OPT_DEBUG) messageSets(strat);
#endif
/* complete reduction of the standard basis--------- */
if (TEST_OPT_REDSB){
completeReduce(strat);
}
/* release temp data-------------------------------- */
exitBuchMora(strat); // cleanT!
id_Delete(&tempF, currRing);
if (TEST_OPT_WEIGHTM)
{
pRestoreDegProcs(pFDegOld, pLDegOld);
if (ecartWeights)
{
omFreeSize((ADDRESS)ecartWeights,(pVariables+1)*sizeof(short));
ecartWeights=NULL;
}
}
if (TEST_OPT_PROT) messageStat(srmax,lrmax,hilbcount,strat);
if (tempQ!=NULL) updateResult(strat->Shdl,tempQ,strat);
if (TEST_OPT_REDSB) // ???
{
// must be at the very end (after exitBuchMora) as it changes the S set!!!
ideal I = strat->Shdl;
ideal erg = kInterRedOld(I,tempQ);
assume(I!=erg);
id_Delete(&I, currRing);
strat->Shdl = erg;
}
#if MYTEST
PrintS("\n\n\n\n");
#endif
return (strat->Shdl);
}
// //////////////////////////////////////////////////////////////////////////////
// sca mora...
// returns TRUE if mora should use buckets, false otherwise
static BOOLEAN kMoraUseBucket(kStrategy strat)
{
#ifdef MORA_USE_BUCKETS
if (TEST_OPT_NOT_BUCKETS)
return FALSE;
if (strat->red == redFirst)
{
#ifdef NO_LDEG
if (!strat->syzComp)
return TRUE;
#else
if ((strat->homog || strat->honey) && !strat->syzComp)
return TRUE;
#endif
}
else
{
assume(strat->red == redEcart);
if (strat->honey && !strat->syzComp)
return TRUE;
}
#endif
return FALSE;
}
#ifdef HAVE_ASSUME
static int sca_mora_count = 0;
static int sca_mora_loop_count;
#endif
// ideal sca_mora (ideal F, ideal Q, intvec *w, intvec *, kStrategy strat)
ideal sca_mora(const ideal F, const ideal Q, const intvec *w, const intvec *, kStrategy strat)
{
assume(rIsSCA(currRing));
const unsigned int m_iFirstAltVar = scaFirstAltVar(currRing);
const unsigned int m_iLastAltVar = scaLastAltVar(currRing);
ideal tempF = id_KillSquares(F, m_iFirstAltVar, m_iLastAltVar, currRing);
ideal tempQ = Q;
if(Q == currQuotient)
tempQ = SCAQuotient(currRing);
bool bIdHomog = id_IsSCAHomogeneous(tempF, NULL, NULL, currRing); // wCx == wCy == NULL!
assume( !bIdHomog || strat->homog ); // bIdHomog =====[implies]>>>>> strat->homog
strat->homog = strat->homog && bIdHomog;
#ifdef PDEBUG
assume( strat->homog == bIdHomog );
#endif /*PDEBUG*/
#ifdef HAVE_ASSUME
sca_mora_count++;
sca_mora_loop_count = 0;
#endif
#ifdef KDEBUG
om_Opts.MinTrack = 5;
#endif
int srmax;
int lrmax = 0;
int olddeg = 0;
int reduc = 0;
int red_result = 1;
// int hilbeledeg=1;
int hilbcount=0;
strat->update = TRUE;
/*- setting global variables ------------------- -*/
initBuchMoraCrit(strat);
// initHilbCrit(F,NULL,&hilb,strat); // no Q!
initMora(tempF, strat);
initBuchMoraPos(strat);
/*Shdl=*/initBuchMora(tempF, tempQ, strat); // temp Q, F!
// if (TEST_OPT_FASTHC) missingAxis(&strat->lastAxis,strat);
/*updateS in initBuchMora has Hecketest
* and could have put strat->kHEdgdeFound FALSE*/
#if 0
if (ppNoether!=NULL)
{
strat->kHEdgeFound = TRUE;
}
if (strat->kHEdgeFound && strat->update)
{
firstUpdate(strat);
updateLHC(strat);
reorderL(strat);
}
if (TEST_OPT_FASTHC && (strat->lastAxis) && strat->posInLOldFlag)
{
strat->posInLOld = strat->posInL;
strat->posInLOldFlag = FALSE;
strat->posInL = posInL10;
updateL(strat);
reorderL(strat);
}
#endif
srmax = strat->sl;
kTest_TS(strat);
strat->use_buckets = kMoraUseBucket(strat);
/*- compute-------------------------------------------*/
#undef HAVE_TAIL_RING
#ifdef HAVE_TAIL_RING
// if (strat->homog && strat->red == redFirst)
// kStratInitChangeTailRing(strat);
#endif
while (strat->Ll >= 0)
{
#ifdef HAVE_ASSUME
sca_mora_loop_count++;
#endif
if (lrmax< strat->Ll) lrmax=strat->Ll; /*stat*/
//test_int_std(strat->kIdeal);
#ifdef KDEBUG
if (TEST_OPT_DEBUG) messageSets(strat);
#endif
if (TEST_OPT_DEGBOUND
&& (strat->L[strat->Ll].ecart+strat->L[strat->Ll].GetpFDeg()> Kstd1_deg))
{
/*
* stops computation if
* - 24 (degBound)
* && upper degree is bigger than Kstd1_deg
*/
while ((strat->Ll >= 0)
&& (strat->L[strat->Ll].p1!=NULL) && (strat->L[strat->Ll].p2!=NULL)
&& (strat->L[strat->Ll].ecart+strat->L[strat->Ll].GetpFDeg()> Kstd1_deg)
)
{
deleteInL(strat->L,&strat->Ll,strat->Ll,strat);
//if (TEST_OPT_PROT)
//{
// PrintS("D"); mflush();
//}
}
if (strat->Ll<0) break;
else strat->noClearS=TRUE;
}
strat->P = strat->L[strat->Ll];/*- picks the last element from the lazyset L -*/
if (strat->Ll==0) strat->interpt=TRUE;
strat->Ll--;
// create the real Spoly
// assume(pNext(strat->P.p) != strat->tail);
if(strat->P.IsNull()) continue;
if( pNext(strat->P.p) == strat->tail )
{
// deletes the int spoly and computes SPoly
pLmFree(strat->P.p); // ???
strat->P.p = nc_CreateSpoly(strat->P.p1, strat->P.p2, currRing);
}
if (strat->P.p1 == NULL)
{
// for input polys, prepare reduction (buckets !)
strat->P.SetLength(strat->length_pLength);
strat->P.PrepareRed(strat->use_buckets);
}
if (!strat->P.IsNull())
{
// might be NULL from noether !!!
if (TEST_OPT_PROT)
message(strat->P.ecart+strat->P.GetpFDeg(),&olddeg,&reduc,strat, red_result);
// reduce
red_result = strat->red(&strat->P,strat);
}
if (! strat->P.IsNull())
{
strat->P.GetP();
// statistics
if (TEST_OPT_PROT) PrintS("s");
// normalization
if (!TEST_OPT_INTSTRATEGY)
strat->P.pNorm();
// tailreduction
strat->P.p = redtail(&(strat->P),strat->sl,strat);
// set ecart -- might have changed because of tail reductions
if ((!strat->noTailReduction) && (!strat->honey))
strat->initEcart(&strat->P);
// cancel unit
cancelunit(&strat->P);
// for char 0, clear denominators
if (TEST_OPT_INTSTRATEGY)
strat->P.pCleardenom();
// put in T
enterT(strat->P,strat);
// build new pairs
enterpairs(strat->P.p,strat->sl,strat->P.ecart,0,strat, strat->tl);
// put in S
strat->enterS(strat->P,
posInS(strat,strat->sl,strat->P.p, strat->P.ecart),
strat, strat->tl);
// clear strat->P
if (strat->P.lcm!=NULL) pLmFree(strat->P.lcm);
strat->P.lcm=NULL;
if (strat->sl>srmax) srmax = strat->sl; /*stat.*/
if (strat->Ll>lrmax) lrmax = strat->Ll;
// //////////////////////////////////////////////////////////
// SCA:
const poly pSave = strat->P.p;
const poly p_next = pNext(pSave);
if(p_next != NULL)
for( unsigned int i = m_iFirstAltVar; i <= m_iLastAltVar; i++ )
if( p_GetExp(pSave, i, currRing) != 0 )
{
assume(p_GetExp(pSave, i, currRing) == 1);
const poly p_new = sca_pp_Mult_xi_pp(i, p_next, currRing);
#ifdef PDEBUG
p_Test(p_new, currRing);
#endif
if( p_new == NULL) continue;
LObject h(p_new); // h = x_i * strat->P
if (TEST_OPT_INTSTRATEGY)
h.pCleardenom(); // also does a pContent
else
h.pNorm();
strat->initEcart(&h);
h.sev = pGetShortExpVector(h.p);
int pos;
if (strat->Ll==-1)
pos = 0;
else
pos = strat->posInL(strat->L,strat->Ll,&h,strat);
enterL(&strat->L,&strat->Ll,&strat->Lmax,h,pos);
if (strat->Ll>lrmax) lrmax = strat->Ll;
}
#ifdef KDEBUG
// make sure kTest_TS does not complain about strat->P
memset(&strat->P,0,sizeof(strat->P));
#endif
}
#if 0
if (strat->kHEdgeFound)
{
if ((BTEST1(27))
|| ((TEST_OPT_MULTBOUND) && (scMult0Int((strat->Shdl)) < mu)))
{
// obachman: is this still used ???
/*
* stops computation if strat->kHEdgeFound and
* - 27 (finiteDeterminacyTest)
* or
* - 23
* (multBound)
* && multiplicity of the ideal is smaller then a predefined number mu
*/
while (strat->Ll >= 0) deleteInL(strat->L,&strat->Ll,strat->Ll,strat);
}
}
#endif
kTest_TS(strat);
}
/*- complete reduction of the standard basis------------------------ -*/
if (TEST_OPT_REDSB) completeReduce(strat);
/*- release temp data------------------------------- -*/
exitBuchMora(strat);
/*- polynomials used for HECKE: HC, noether -*/
if (BTEST1(27))
{
if (strat->kHEdge!=NULL)
Kstd1_mu=pFDeg(strat->kHEdge,currRing);
else
Kstd1_mu=-1;
}
pDelete(&strat->kHEdge);
strat->update = TRUE; //???
strat->lastAxis = 0; //???
pDelete(&strat->kNoether);
omFreeSize((ADDRESS)strat->NotUsedAxis,(pVariables+1)*sizeof(BOOLEAN));
if (TEST_OPT_PROT) messageStat(srmax,lrmax,hilbcount,strat);
if (TEST_OPT_WEIGHTM)
{
pRestoreDegProcs(pFDegOld, pLDegOld);
if (ecartWeights)
{
omFreeSize((ADDRESS)ecartWeights,(pVariables+1)*sizeof(short));
ecartWeights=NULL;
}
}
if (tempQ!=NULL) updateResult(strat->Shdl,tempQ,strat);
idTest(strat->Shdl);
id_Delete( &tempF, currRing);
return (strat->Shdl);
}
void sca_p_ProcsSet(ring rGR, p_Procs_s* p_Procs)
{
// "commutative" procedures:
rGR->p_Procs->p_Mult_mm = sca_p_Mult_mm;
rGR->p_Procs->pp_Mult_mm = sca_pp_Mult_mm;
p_Procs->p_Mult_mm = sca_p_Mult_mm;
p_Procs->pp_Mult_mm = sca_pp_Mult_mm;
// non-commutaitve
rGR->GetNC()->p_Procs.mm_Mult_p = sca_mm_Mult_p;
rGR->GetNC()->p_Procs.mm_Mult_pp = sca_mm_Mult_pp;
if (rHasLocalOrMixedOrdering(rGR))
{
#ifdef PDEBUG
// Print("Local case => GB == mora!\n");
#endif
rGR->GetNC()->p_Procs.GB = sca_mora; // local ordering => Mora, otherwise - Buchberger!
}
else
{
#ifdef PDEBUG
// Print("Global case => GB == bba!\n");
#endif
rGR->GetNC()->p_Procs.GB = sca_bba; // sca_gr_bba; // sca_bba? // sca_bba;
}
// rGR->GetNC()->p_Procs.GlobalGB = sca_gr_bba;
// rGR->GetNC()->p_Procs.LocalGB = sca_mora;
// rGR->GetNC()->p_Procs.SPoly = sca_SPoly;
// rGR->GetNC()->p_Procs.ReduceSPoly = sca_ReduceSpoly;
#if 0
// Multiplication procedures:
p_Procs->p_Mult_mm = sca_p_Mult_mm;
_p_procs->p_Mult_mm = sca_p_Mult_mm;
p_Procs->pp_Mult_mm = sca_pp_Mult_mm;
_p_procs->pp_Mult_mm = sca_pp_Mult_mm;
r->GetNC()->mmMultP() = sca_mm_Mult_p;
r->GetNC()->mmMultPP() = sca_mm_Mult_pp;
r->GetNC()->GB() = sca_gr_bba;
/*
// ??????????????????????????????????????? coefficients swell...
r->GetNC()->SPoly() = sca_SPoly;
r->GetNC()->ReduceSPoly() = sca_ReduceSpoly;
*/
// r->GetNC()->BucketPolyRed() = gnc_kBucketPolyRed;
// r->GetNC()->BucketPolyRed_Z()= gnc_kBucketPolyRed_Z;
#endif
}
// bi-Degree (x, y) of monomial "m"
// x-es and y-s are weighted by wx and wy resp.
// [optional] components have weights by wCx and wCy.
inline void m_GetBiDegree(const poly m,
const intvec *wx, const intvec *wy,
const intvec *wCx, const intvec *wCy,
int& dx, int& dy, const ring r)
{
const unsigned int N = r->N;
p_Test(m, r);
assume( wx != NULL );
assume( wy != NULL );
assume( wx->cols() == 1 );
assume( wy->cols() == 1 );
assume( (unsigned int)wx->rows() >= N );
assume( (unsigned int)wy->rows() >= N );
int x = 0;
int y = 0;
for(int i = N; i > 0; i--)
{
const int d = p_GetExp(m, i, r);
x += d * (*wx)[i-1];
y += d * (*wy)[i-1];
}
if( (wCx != NULL) && (wCy != NULL) )
{
const int c = p_GetComp(m, r);
if( wCx->range(c) )
x += (*wCx)[c];
if( wCy->range(c) )
x += (*wCy)[c];
}
dx = x;
dy = y;
}
// returns true if polynom p is bi-homogenous with respect to the given weights
// simultaneously sets bi-Degree
bool p_IsBiHomogeneous(const poly p,
const intvec *wx, const intvec *wy,
const intvec *wCx, const intvec *wCy,
int &dx, int &dy,
const ring r)
{
if( p == NULL )
{
dx = 0;
dy = 0;
return true;
}
poly q = p;
int ddx, ddy;
m_GetBiDegree( q, wx, wy, wCx, wCy, ddx, ddy, r); // get bi degree of lm(p)
pIter(q);
for(; q != NULL; pIter(q) )
{
int x, y;
m_GetBiDegree( q, wx, wy, wCx, wCy, x, y, r); // get bi degree of q
if ( (x != ddx) || (y != ddy) ) return false;
}
dx = ddx;
dy = ddy;
return true;
}
// returns true if id is bi-homogenous without respect to the given weights
bool id_IsBiHomogeneous(const ideal id,
const intvec *wx, const intvec *wy,
const intvec *wCx, const intvec *wCy,
const ring r)
{
if (id == NULL) return true; // zero ideal
const int iSize = IDELEMS(id);
if (iSize == 0) return true;
bool b = true;
int x, y;
for(int i = iSize - 1; (i >= 0 ) && b; i--)
b = p_IsBiHomogeneous(id->m[i], wx, wy, wCx, wCy, x, y, r);
return b;
}
// returns an intvector with [nvars(r)] integers [1/0]
// 1 - for commutative variables
// 0 - for anticommutative variables
intvec *ivGetSCAXVarWeights(const ring r)
{
const unsigned int N = r->N;
const int CommutativeVariable = 0; // bug correction!
const int AntiCommutativeVariable = 0;
intvec* w = new intvec(N, 1, CommutativeVariable);
if(AntiCommutativeVariable != CommutativeVariable)
if( rIsSCA(r) )
{
const unsigned int m_iFirstAltVar = scaFirstAltVar(r);
const unsigned int m_iLastAltVar = scaLastAltVar(r);
for (unsigned int i = m_iFirstAltVar; i<= m_iLastAltVar; i++)
{
(*w)[i-1] = AntiCommutativeVariable;
}
}
return w;
}
// returns an intvector with [nvars(r)] integers [1/0]
// 0 - for commutative variables
// 1 - for anticommutative variables
intvec *ivGetSCAYVarWeights(const ring r)
{
const unsigned int N = r->N;
const int CommutativeVariable = 0;
const int AntiCommutativeVariable = 1;
intvec* w = new intvec(N, 1, CommutativeVariable);
if(AntiCommutativeVariable != CommutativeVariable)
if( rIsSCA(r) )
{
const unsigned int m_iFirstAltVar = scaFirstAltVar(r);
const unsigned int m_iLastAltVar = scaLastAltVar(r);
for (unsigned int i = m_iFirstAltVar; i<= m_iLastAltVar; i++)
{
(*w)[i-1] = AntiCommutativeVariable;
}
}
return w;
}
// reduce term lt(m) modulo , i = iFirstAltVar .. iLastAltVar:
// either create a copy of m or return NULL
inline poly m_KillSquares(const poly m,
const unsigned int iFirstAltVar, const unsigned int iLastAltVar,
const ring r)
{
#ifdef PDEBUG
p_Test(m, r);
assume( (iFirstAltVar >= 1) && (iLastAltVar <= r->N) && (iFirstAltVar <= iLastAltVar) );
#if 0
Print("m_KillSquares, m = "); // !
p_Write(m, r);
#endif
#endif
assume( m != NULL );
for(unsigned int k = iFirstAltVar; k <= iLastAltVar; k++)
if( p_GetExp(m, k, r) > 1 )
return NULL;
return p_Head(m, r);
}
// reduce polynomial p modulo , i = iFirstAltVar .. iLastAltVar
poly p_KillSquares(const poly p,
const unsigned int iFirstAltVar, const unsigned int iLastAltVar,
const ring r)
{
#ifdef PDEBUG
p_Test(p, r);
assume( (iFirstAltVar >= 1) && (iLastAltVar <= r->N) && (iFirstAltVar <= iLastAltVar) );
#if 0
Print("p_KillSquares, p = "); // !
p_Write(p, r);
#endif
#endif
if( p == NULL )
return NULL;
poly pResult = NULL;
poly* ppPrev = &pResult;
for( poly q = p; q!= NULL; pIter(q) )
{
#ifdef PDEBUG
p_Test(q, r);
#endif
// terms will be in the same order because of quasi-ordering!
poly v = m_KillSquares(q, iFirstAltVar, iLastAltVar, r);
if( v != NULL )
{
*ppPrev = v;
ppPrev = &pNext(v);
}
}
#ifdef PDEBUG
p_Test(pResult, r);
#if 0
Print("p_KillSquares => "); // !
p_Write(pResult, r);
#endif
#endif
return(pResult);
}
// reduces ideal id modulo , i = iFirstAltVar .. iLastAltVar
// returns the reduced ideal or zero ideal.
ideal id_KillSquares(const ideal id,
const unsigned int iFirstAltVar, const unsigned int iLastAltVar,
const ring r, const bool bSkipZeroes)
{
if (id == NULL) return id; // zero ideal
assume( (iFirstAltVar >= 1) && (iLastAltVar <= r->N) && (iFirstAltVar <= iLastAltVar) );
const int iSize = IDELEMS(id);
if (iSize == 0) return id;
ideal temp = idInit(iSize, id->rank);
#if 0
PrintS("\n");
{
PrintS("ideal id: \n");
for (int i = 0; i < IDELEMS(id); i++)
{
Print("; id[%d] = ", i+1);
p_Write(id->m[i], r);
}
PrintS(";\n");
PrintLn();
}
#endif
for (int j = 0; j < iSize; j++)
temp->m[j] = p_KillSquares(id->m[j], iFirstAltVar, iLastAltVar, r);
if( bSkipZeroes )
idSkipZeroes(temp);
#if 0
PrintS("\n");
{
PrintS("ideal temp: \n");
for (int i = 0; i < IDELEMS(temp); i++)
{
Print("; temp[%d] = ", i+1);
p_Write(temp->m[i], r);
}
PrintS(";\n");
PrintLn();
}
PrintS("\n");
#endif
// temp->rank = idRankFreeModule(temp, r);
return temp;
}
#endif