// emacs edit mode for this file is -*- C++ -*- // $Id: fglmvec.cc,v 1.2 2007-05-15 13:51:42 Singular Exp $ /**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT - The FGLM-Algorithm * Implementation of number-vectors for the fglm algorithm. * (See fglm.cc). Based on a letter-envelope implementation, mainly * written to be used by the fglm algorithm. Hence they are * specialized for this purpose. */ #include "mod2.h" #ifdef HAVE_FGLM #include "omalloc.h" #include "structs.h" #include "numbers.h" #include "fglm.h" #include "fglmvec.h" #define PROT(msg) #define STICKYPROT(msg) if (BTEST1(OPT_PROT)) Print(msg) #define PROT2(msg,arg) #define STICKYPROT2(msg,arg) if (BTEST1(OPT_PROT)) Print(msg,arg) #define fglmASSERT(ignore1,ignore2) class fglmVectorRep { private: int ref_count; int N; number * elems; public: fglmVectorRep() : ref_count(1), N(0), elems(0) {} fglmVectorRep( int n, number * e ) : ref_count(1), N(n), elems(e) {} fglmVectorRep( int n ) : ref_count(1), N(n) { fglmASSERT( N >= 0, "illegal Vector representation" ); if ( N == 0 ) elems= 0; else { elems= (number *)omAlloc( N*sizeof( number ) ); for ( int i= N-1; i >= 0; i-- ) elems[i]= nInit( 0 ); } } ~fglmVectorRep() { if ( N > 0 ) { for ( int i= N-1; i >= 0; i-- ) nDelete( elems + i ); omFreeSize( (ADDRESS)elems, N*sizeof( number ) ); } } fglmVectorRep* clone() const { if ( N > 0 ) { number * elems_clone; elems_clone= (number *)omAlloc( N*sizeof( number ) ); for ( int i= N-1; i >= 0; i-- ) elems_clone[i] = nCopy( elems[i] ); return new fglmVectorRep( N, elems_clone ); } else return new fglmVectorRep( N, 0 ); } BOOLEAN deleteObject() { return --ref_count == 0; } fglmVectorRep * copyObject() { ref_count++; return this; } int refcount() const { return ref_count; } BOOLEAN isUnique() const { return ref_count == 1; } int size() const { return N; } int isZero() const { int k; for ( k= N; k > 0; k-- ) if ( ! nIsZero( getconstelem( k ) ) ) return 0; return 1; } int numNonZeroElems() const { int num = 0; int k; for ( k= N; k > 0; k-- ) if ( ! nIsZero( getconstelem( k ) ) ) num++; return num; } void setelem( int i, number n ) { fglmASSERT( 0 < i && i <= N, "setelem: wrong index" ); nDelete( elems + i-1 ); elems[i-1]= n; } number ejectelem( int i, number n ) { fglmASSERT( isUnique(), "should only be called if unique!" ); number temp= elems[i-1]; elems[i-1]= n; return temp; } number & getelem( int i ) { fglmASSERT( 0 < i && i <= N, "getelem: wrong index" ); return elems[i-1]; } const number getconstelem( int i) const { fglmASSERT( 0 < i && i <= N, "getconstelem: wrong index" ); return elems[i-1]; } friend class fglmVector; }; ///-------------------------------------------------------------------------------- /// Implementation of class fglmVector ///-------------------------------------------------------------------------------- fglmVector::fglmVector( fglmVectorRep * r ) : rep(r) {} fglmVector::fglmVector() : rep( new fglmVectorRep() ) {} fglmVector::fglmVector( int size ) : rep( new fglmVectorRep( size ) ) {} fglmVector::fglmVector( int size, int basis ) : rep( new fglmVectorRep( size ) ) { rep->setelem( basis, nInit( 1 ) ); } fglmVector::fglmVector( const fglmVector & v ) { rep= v.rep->copyObject(); } fglmVector::~fglmVector() { if ( rep->deleteObject() ) delete rep; } #ifndef HAVE_EXPLICIT_CONSTR void fglmVector::mac_constr( const fglmVector & v) { rep= v.rep->copyObject(); } void fglmVector::mac_constr_i( int size ) { rep= new fglmVectorRep( size ); } void fglmVector::clearelems() { if ( rep->deleteObject() ) delete rep; } #endif void fglmVector::makeUnique() { if ( rep->refcount() != 1 ) { rep->deleteObject(); rep= rep->clone(); } } int fglmVector::size() const { return rep->size(); } int fglmVector::numNonZeroElems() const { return rep->numNonZeroElems(); } void fglmVector::nihilate( const number fac1, const number fac2, const fglmVector v ) { int i; int vsize= v.size(); number term1, term2; fglmASSERT( vsize <= rep->size(), "v has to be smaller oder equal" ); if ( rep->isUnique() ) { for ( i= vsize; i > 0; i-- ) { term1= nMult( fac1, rep->getconstelem( i ) ); term2= nMult( fac2, v.rep->getconstelem( i ) ); rep->setelem( i, nSub( term1, term2 ) ); nDelete( &term1 ); nDelete( &term2 ); } for ( i= rep->size(); i > vsize; i-- ) { rep->setelem( i, nMult( fac1, rep->getconstelem( i ) ) ); } } else { number* newelems; newelems= (number *)omAlloc( rep->size()*sizeof( number ) ); for ( i= vsize; i > 0; i-- ) { term1= nMult( fac1, rep->getconstelem( i ) ); term2= nMult( fac2, v.rep->getconstelem( i ) ); newelems[i-1]= nSub( term1, term2 ); nDelete( &term1 ); nDelete( &term2 ); } for ( i= rep->size(); i > vsize; i-- ) { newelems[i-1]= nMult( fac1, rep->getconstelem( i ) ); } rep->deleteObject(); rep= new fglmVectorRep( rep->size(), newelems ); } } fglmVector & fglmVector::operator = ( const fglmVector & v ) { if ( this != &v ) { if ( rep->deleteObject() ) delete rep; rep = v.rep->copyObject(); } return *this; } int fglmVector::operator == ( const fglmVector & v ) { if ( rep->size() == v.rep->size() ) { if ( rep == v.rep ) return 1; else { int i; for ( i= rep->size(); i > 0; i-- ) if ( ! nEqual( rep->getconstelem( i ), v.rep->getconstelem( i ) ) ) return 0; return 1; } } return 0; } int fglmVector::operator != ( const fglmVector & v ) { return !( *this == v ); } int fglmVector::isZero() { return rep->isZero(); } int fglmVector::elemIsZero( int i ) { return nIsZero( rep->getconstelem( i ) ); } fglmVector & fglmVector::operator += ( const fglmVector & v ) { fglmASSERT( size() == v.size(), "incompatible vectors" ); // ACHTUNG : Das Verhalten hier mit gcd genau ueberpruefen! int i; if ( rep->isUnique() ) { for ( i= rep->size(); i > 0; i-- ) rep->setelem( i, nAdd( rep->getconstelem( i ), v.rep->getconstelem( i ) ) ); } else { int n = rep->size(); number* newelems; newelems= (number *)omAlloc( n*sizeof( number ) ); for ( i= n; i > 0; i-- ) newelems[i-1]= nAdd( rep->getconstelem( i ), v.rep->getconstelem( i ) ); rep->deleteObject(); rep= new fglmVectorRep( n, newelems ); } return *this; } fglmVector & fglmVector::operator -= ( const fglmVector & v ) { fglmASSERT( size() == v.size(), "incompatible vectors" ); int i; if ( rep->isUnique() ) { for ( i= rep->size(); i > 0; i-- ) rep->setelem( i, nSub( rep->getconstelem( i ), v.rep->getconstelem( i ) ) ); } else { int n = rep->size(); number* newelems; newelems= (number *)omAlloc( n*sizeof( number ) ); for ( i= n; i > 0; i-- ) newelems[i-1]= nSub( rep->getconstelem( i ), v.rep->getconstelem( i ) ); rep->deleteObject(); rep= new fglmVectorRep( n, newelems ); } return *this; } fglmVector & fglmVector::operator *= ( const number & n ) { int s= rep->size(); int i; if ( ! rep->isUnique() ) { number * temp; temp= (number *)omAlloc( s*sizeof( number ) ); for ( i= s; i > 0; i-- ) temp[i-1]= nMult( rep->getconstelem( i ), n ); rep->deleteObject(); rep= new fglmVectorRep( s, temp ); } else { for (i= s; i > 0; i-- ) rep->setelem( i, nMult( rep->getconstelem( i ), n ) ); } return *this; } fglmVector & fglmVector::operator /= ( const number & n ) { int s= rep->size(); int i; if ( ! rep->isUnique() ) { number * temp; temp= (number *)omAlloc( s*sizeof( number ) ); for ( i= s; i > 0; i-- ) { temp[i-1]= nDiv( rep->getconstelem( i ), n ); nNormalize( temp[i-1] ); } rep->deleteObject(); rep= new fglmVectorRep( s, temp ); } else { for (i= s; i > 0; i-- ) { rep->setelem( i, nDiv( rep->getconstelem( i ), n ) ); nNormalize( rep->getelem( i ) ); } } return *this; } fglmVector operator - ( const fglmVector & v ) { fglmVector temp( v.size() ); int i; number n ; for ( i= v.size(); i > 0; i-- ) { n= nCopy( v.getconstelem( i ) ); n= nNeg( n ); temp.setelem( i, n ); } return temp; } fglmVector operator + ( const fglmVector & lhs, const fglmVector & rhs ) { fglmVector temp= lhs; temp+= rhs; return temp; } fglmVector operator - ( const fglmVector & lhs, const fglmVector & rhs ) { fglmVector temp= lhs; temp-= rhs; return temp; } fglmVector operator * ( const fglmVector & v, const number n ) { fglmVector temp= v; temp*= n; return temp; } fglmVector operator * ( const number n, const fglmVector & v ) { fglmVector temp= v; temp*= n; return temp; } number & fglmVector::getelem( int i ) { makeUnique(); return rep->getelem( i ); } const number fglmVector::getconstelem( int i ) const { return rep->getconstelem( i ); } void fglmVector::setelem( int i, number & n ) { makeUnique(); rep->setelem( i, n ); n= nNULL; } number fglmVector::gcd() const { int i= rep->size(); BOOLEAN found = FALSE; BOOLEAN gcdIsOne = FALSE; number theGcd; number current; while( i > 0 && ! found ) { current= rep->getconstelem( i ); if ( ! nIsZero( current ) ) { theGcd= nCopy( current ); found= TRUE; if ( ! nGreaterZero( theGcd ) ) { theGcd= nNeg( theGcd ); } if ( nIsOne( theGcd ) ) gcdIsOne= TRUE; } i--; } if ( found ) { while ( i > 0 && ! gcdIsOne ) { current= rep->getconstelem( i ); if ( ! nIsZero( current ) ) { number temp= nGcd( theGcd, current, currRing ); nDelete( &theGcd ); theGcd= temp; if ( nIsOne( theGcd ) ) gcdIsOne= TRUE; } i--; } } else theGcd= nInit( 0 ); return theGcd; } number fglmVector::clearDenom() { number theLcm = nInit( 1 ); number current; BOOLEAN isZero = TRUE; int i; for ( i= size(); i > 0; i-- ) { if ( ! nIsZero( rep->getconstelem(i) ) ) { isZero= FALSE; number temp= nLcm( theLcm, rep->getconstelem( i ), currRing ); nDelete( &theLcm ); theLcm= temp; } } if ( isZero ) { nDelete( &theLcm ); theLcm= nInit( 0 ); } else { if ( ! nIsOne( theLcm ) ) { *this *= theLcm; for ( i= size(); i > 0; i-- ) { nNormalize( rep->getelem( i ) ); } } } return theLcm; } #endif // ---------------------------------------------------------------------------- // Local Variables: *** // compile-command: "make Singular" *** // page-delimiter: "^\\( \\|//!\\)" *** // fold-internal-margins: nil *** // End: ***