Loading...
Searching...
No Matches
cf_inline.cc
Go to the documentation of this file.
/* emacs edit mode for this file is -*- C++ -*- */
/**
*
* @file cf_inline.cc
*
* definition of configurable inline
* `CanonicalForm' methods.
*
* Hierarchy: canonicalform
*
* Header file: canonicalform.h
*
* Developers note:
* ----------------
* The central class in Factory is, of course, `CanonicalForm'.
* Hence it is a quiet reasonable to assume that inlining its
* most important methods will improve execution speed. The same
* holds for some methods of the `CFIterator' class. Everything
* on configurable inline `CanonicalForm' methods explained here
* applies mutatis mutandis to the `CFIterator' methods.
*
* However, inlining `CanonicalForm' methods has two major
* drawbacks:
*
* o If `CanonicalForm' methods simply would have been declared
* `inline' it would have been necessary to include the
* definition of `InternalCF' in `factory.h'. This would have
* been quite a contradiction to the internal nature of the
* class.
* Hence it seemed desirable to introduce a mechanism to have
* both the inlined versions for internal use and compiled
* versions for the library.
*
* o Second, inlining in most cases leads to larger object code.
* E.g., inlining `CanonicalForm::~CanonicalForm()' increases the
* object code by approx. 15% without any effect on computation
* speed.
* Thus another design aim was to keep things configurable.
* That is why the methods defined here are called
* "configurable inline methods".
*
* The low level solution to both problems is the macro
* `CF_INLINE' which either expands to `inline' or nothing. The
* counterpart `CF_NO_INLINE' exists only for convenience, it
* always expands to nothing. `CF_INLINE' is set immediately
* before defining resp. declaring the methods to exclude any
* esoteric influences from included files.
*
* The high level interface is the macro `CF_USE_INLINE'. If it
* is defined any header file that uses configurable inline
* methods defines them to be `inline', otherwise they are
* defined as ordinary methods. `CF_USE_INLINE' is defined in
* `config.h' only.
*
* To switch on (off) all configurable inline methods, it is
* sufficient to define (undefine) `CF_USE_INLINE' in `config.h'.
* To switch off separate configurable inline methods it is
* necessary to prefix their declaration in `canonicalform.h' by
* `CF_NO_INLINE' instead of `CF_INLINE'. Furthermore, to avoid
* duplicate symbols at link time, their definition in this file
* has to be wrapped by an `#ifndef INCL_CF_INLINE_CC'.
*
* It turned out that inlining the following methods (and only
* them) results in the best time to size ratio on Linux and HP
* machines:
* o all `CanonicalForm' constructors
* o the binary `CanonicalForm' operators `+' and `*'
*
**/
// check whether we are included or translated and
// define `INCL_CF_INLINE_CC' if we are included
#ifdef INCL_CANONICALFORM_H
#define INCL_CF_INLINE_CC
#endif
#include "config.h"
#include "cf_assert.h"
// temporarily switch off `CF_USE_INLINE' and include
// `canonicalform.h' if we are being translated.
// `CF_USE_INLINE_SAVE' is used to save the state of
// `CF_USE_INLINE'. It is unset after use.
#ifndef INCL_CF_INLINE_CC
#ifdef CF_USE_INLINE
#define CF_USE_INLINE_SAVE
#undef CF_USE_INLINE
#endif
#include "canonicalform.h"
#ifdef CF_USE_INLINE_SAVE
#define CF_USE_INLINE
#undef CF_USE_INLINE_SAVE
#endif
#endif /* ! INCL_CF_INLINE_CC */
// regular include files
#include "int_cf.h"
#include "imm.h"
#include "cf_factory.h"
// set the value of `CF_INLINE' for the following methods and
// functions
#if defined( CF_USE_INLINE ) && defined( INCL_CF_INLINE_CC )
#ifndef __CYGWIN__
#undef CF_INLINE
#define CF_INLINE inline
#endif
#else
#undef CF_INLINE
#define CF_INLINE
#endif /* ! defined( CF_USE_INLINE ) && defined( INCL_CF_INLINE_CC ) */
// constructors, destructors, assignment
/** CF_INLINE CanonicalForm::CanonicalForm ()
*
*
* CanonicalForm() - create the default canonical form.
*
* The canonical form is initialized to zero from the current
* domain.
*
**/
CF_INLINE
CanonicalForm::CanonicalForm ()
: value( CFFactory::basic( 0 ) )
{
}
/** CF_INLINE CanonicalForm::CanonicalForm ( const int i )
*
*
* CanonicalForm() - create a canonical form from an integer.
*
* The canonical form is initialized to the "canonical image" of
* `i' in the current domain. This is `i' itself for
* characteristic zero, `i' mod p for finite fields of
* characteristic p, and `i' mod p^n for prime power domains with
* p^n elements.
*
**/
#if SIZEOF_LONG == 8
CF_INLINE
CanonicalForm::CanonicalForm ( const int i )
: value( CFFactory::basic( i ) )
#else
CF_INLINE
CanonicalForm::CanonicalForm ( const int i )
: value( CFFactory::basic( (long)i ) )
#endif
{
}
CF_INLINE
CanonicalForm::CanonicalForm ( const long i )
: value( CFFactory::basic( i ) )
{
}
/** CF_INLINE CanonicalForm::CanonicalForm ( const CanonicalForm & cf )
*
*
* CanonicalForm() - create a copy of a canonical form.
*
* Type info:
* ----------
* cf: Anything
*
**/
CF_INLINE
CanonicalForm::CanonicalForm ( const CanonicalForm & cf )
: value( is_imm( cf.value ) ? cf.value : cf.value->copyObject() )
{
}
/** CF_INLINE CanonicalForm::CanonicalForm ( InternalCF * cf )
*
*
* CanonicalForm() - create a canonical form from a pointer to an
* internal canonical form.
*
* This constructor is reserved for internal usage.
*
* Developers note:
* ----------------
* The canonical form gets its value immediately from `cf'.
* `cf's reference counter is not incremented, so be careful with
* this constructor.
*
**/
CF_INLINE
CanonicalForm::CanonicalForm ( InternalCF * cf )
: value( cf )
{
}
/** CF_INLINE CanonicalForm::CanonicalForm ( const Variable & v )
*
*
* CanonicalForm() - create a canonical form from a variable.
*
* If `v' is a polynomial variable or an algebraic element the
* resulting polynomial (or algebraic element) is 1*`v'^1, the
* one being from the current domain.
*
* Variables of level `LEVELBASE' are transformed to one from the
* current domain.
*
* Type info:
* ----------
* v: Anything
*
**/
CF_INLINE
CanonicalForm::CanonicalForm ( const Variable & v )
: value( CFFactory::poly( v ) )
{
}
/** CF_INLINE CanonicalForm::CanonicalForm ( const Variable & v, int e )
*
*
* CanonicalForm() - create a canonical form from a power of a
* variable.
*
* If `v' is a polynomial variable or an algebraic element the
* resulting polynomial (or algebraic element) is 1*`v'^`e', the
* one being from the current domain. Algebraic elements are
* reduced modulo their minimal polynomial.
*
* Variables of level `LEVELBASE' are transformed to one from the
* current domain.
*
* Type info:
* ----------
* v: Anything
*
**/
CF_INLINE
CanonicalForm::CanonicalForm ( const Variable & v, int e )
: value( CFFactory::poly( v, e ) )
{
//ASSERT( e > 0, "math error: exponent has to be positive" );
}
#ifndef INCL_CF_INLINE_CC
/** CF_INLINE CanonicalForm::~CanonicalForm ()
*
*
* ~CanonicalForm() - delete CO.
*
* Type info:
* ----------
* CO: Anything
*
**/
CF_INLINE
CanonicalForm::~CanonicalForm ()
{
if ( (! is_imm( value )) && value->deleteObject() )
delete value;
}
#endif
#ifndef INCL_CF_INLINE_CC
/** CF_INLINE CanonicalForm & CanonicalForm::operator = ( const CanonicalForm & cf )
*
*
* operator =() - assign `cf' to CO.
*
* Type info:
* ----------
* CO, cf: Anything
*
**/
CF_INLINE CanonicalForm &
CanonicalForm::operator = ( const CanonicalForm & cf )
{
if ( this != &cf ) {
if ( (! is_imm( value )) && value->deleteObject() )
delete value;
value = (is_imm( cf.value )) ? cf.value : cf.value->copyObject();
}
return *this;
}
/**
*
* operator =() - assign long `cf' to CO.
*
* `cf' converted to a canonical form as described in the
* canonical form constructor which creates a canonical form from
* an integer.
*
* Type info:
* ----------
* CO: Anything
*
* Developers note:
* ----------------
* Strictly speaking, this operator is superfluous. The ordinary
* assignment operator together with automatic conversion from
* `int' to `CanonicalForm' would do the job, too. But this way
* the common operation of assigning an integer is faster.
*
**/
CF_INLINE CanonicalForm &
CanonicalForm::operator = ( const long cf )
{
if ( (! is_imm( value )) && value->deleteObject() )
delete value;
value = CFFactory::basic( cf );
return *this;
}
#endif
// predicates
#ifndef INCL_CF_INLINE_CC
/** CF_INLINE bool CanonicalForm::isOne, isZero () const
*
*
* isOne(), isZero() - test whether a `CanonicalForm' equals one
* or zero, resp.
*
* The predicates `isOne()' and `isZero()' are much faster than
* the comparison operators. Furthermore, a test `f.isZero()' is
* independent from the current domain, whereas an expression
* `f == 0' is not.
*
* Type info:
* ----------
* CO: Anything
*
* Internal implementation:
* ------------------------
* Note that only immediate objects and objects of class
* `InternalPrimePower' may equal one or zero, resp.
*
* imm_isone(), imm_iszero()
* Trivial.
*
* imm_isone_p(), imm_iszero_p()
* Trivial.
*
* imm_isone_gf(), imm_iszero_gf()
* Use `gf_isone()' and `gf_iszero()', resp., to test whether CO
* equals zero or one, resp.
*
* InternalCF::isOne(), isZero()
* Always return false.
*
* InternalPrimePower::isOne(), isZero()
* Use `mpz_cpm_ui()' resp. `mpz_sgn()' to check the underlying
* mpi.
*
* @sa CanonicalForm::isZero()
**/
CF_INLINE bool
CanonicalForm::isOne () const
{
int what = is_imm( value );
if ( ! what )
return value->isOne();
else if ( what == INTMARK )
return imm_isone( value );
else if ( what == FFMARK )
return imm_isone_p( value );
else
return imm_isone_gf( value );
}
/**
* @sa CanonicalForm::isOne()
**/
CF_INLINE bool
CanonicalForm::isZero () const
{
int what = is_imm( value );
if ( what == 0 )
return value->isZero();
else if ( what == INTMARK )
return imm_iszero( value );
else if ( what == FFMARK )
return imm_iszero_p( value );
else
return imm_iszero_gf( value );
}
#endif
// arithmetic operators
#ifndef INCL_CF_INLINE_CC
/** CF_INLINE CanonicalForm operator - ( const CanonicalForm & cf )
*
*
* operator -() - return additive inverse of `cf'.
*
* Returns the additive inverse of `cf'. One should keep in mind
* that to negate a canonical form a complete (deep) copy of it
* has to be created.
*
* Type info:
* ----------
* cf: CurrentPP
*
* In fact, the type is almost `Anything', but it is, e.g., not
* possible to invert an element from a finite field when the
* characteristic of the current domain has changed.
*
* Internal implementation:
* ------------------------
* All internal methods check whether the reference counter
* equals one. If so CO is negated in-place. Otherwise, a new
* copy of CO is created and negated.
*
* imm_neg()
* Trivial.
*
* imm_neg_p()
* Use `ff_neg()' to negate CO.
*
* imm_neg_gf()
* Use `gf_neg()' to negate CO.
*
* InternalInteger::neg()
* Use `mpz_neg()' to negate the underlying mpi.
*
* InternalRational::neg ()
* Use `mpz_neg()' to negate the denominator.
*
* InternalPrimePower::neg()
* Subtract CO from `primepow' using `mpz_sub'.
*
* InternalPoly::neg()
* If reference counter is one use `negateTermList()' to negate
* the terms, otherwise create a negated copy using
* `copyTermList()'.
*
* @sa CanonicalForm::operator -=()
**/
CF_INLINE CanonicalForm
operator - ( const CanonicalForm & cf )
{
CanonicalForm result( cf );
int what = is_imm( result.value );
if ( ! what )
result.value = result.value->neg();
else if ( what == INTMARK )
result.value = imm_neg( result.value );
else if ( what == FFMARK )
result.value = imm_neg_p( result.value );
else
result.value = imm_neg_gf( result.value );
return result;
}
#endif
// binary arithmetic operators and functions
/** CF_INLINE CanonicalForm operator +, -, *, /, % ( const CanonicalForm & lhs, const CanonicalForm & rhs )
*
*
* operators +, -, *, /, %(), div(), mod() - binary arithmetic
* operators.
*
* The binary operators have their standard (mathematical)
* semantics. As explained for the corresponding arithmetic
* assignment operators, the operators `/' and `%' return the
* quotient resp. remainder of (polynomial) division with
* remainder, whereas `div()' and `mod()' may be used for exact
* division and term-wise remaindering, resp.
*
* It is faster to use the arithmetic assignment operators (e.g.,
* `f += g;') instead of the binary operators (`f = f+g;' ).
*
* Type info:
* ----------
* lhs, rhs: CurrentPP
*
* There are weaker preconditions for some cases (e.g.,
* arithmetic operations with elements from Q or Z work in any
* domain), but type `CurrentPP' is the only one guaranteed to
* work for all cases.
*
* Developers note:
* ----------------
* All binary operators have their corresponding `CanonicalForm'
* assignment operators (e.g., `operator +()' corresponds to
* `CanonicalForm::operator +=()', `div()' corresponds to
* `CanonicalForm::div()).
*
* And that is how they are implemented, too: Each of the binary
* operators first creates a copy of `lhs', adds `rhs' to this
* copy using the assignment operator, and returns the result.
*
* @sa CanonicalForm::operator +=()
**/
CF_INLINE CanonicalForm FACTORY_PUBLIC
operator + ( const CanonicalForm & lhs, const CanonicalForm & rhs )
{
CanonicalForm result( lhs );
result += rhs;
return result;
}
#ifndef INCL_CF_INLINE_CC
CF_INLINE CanonicalForm FACTORY_PUBLIC
operator - ( const CanonicalForm & lhs, const CanonicalForm & rhs )
{
CanonicalForm result( lhs );
result -= rhs;
return result;
}
#endif
/**
* @sa CanonicalForm::operator *=()
**/
CF_INLINE CanonicalForm FACTORY_PUBLIC
operator * ( const CanonicalForm & lhs, const CanonicalForm & rhs )
{
CanonicalForm result( lhs );
result *= rhs;
return result;
}
#ifndef INCL_CF_INLINE_CC
/**
* @sa CanonicalForm::operator /=()
**/
CF_INLINE CanonicalForm FACTORY_PUBLIC
operator / ( const CanonicalForm & lhs, const CanonicalForm & rhs )
{
CanonicalForm result( lhs );
result /= rhs;
return result;
}
/**
* @sa CanonicalForm::operator %=()
**/
CF_INLINE CanonicalForm FACTORY_PUBLIC
operator % ( const CanonicalForm & lhs, const CanonicalForm & rhs )
{
CanonicalForm result( lhs );
result %= rhs;
return result;
}
#endif
#ifndef INCL_CF_INLINE_CC
/** CF_INLINE CanonicalForm div, mod ( const CanonicalForm & lhs, const CanonicalForm & rhs )
* @sa mod(), operator/(), CanonicalForm::operator /=()
**/
CF_INLINE CanonicalForm
div ( const CanonicalForm & lhs, const CanonicalForm & rhs )
{
CanonicalForm result( lhs );
result.div( rhs );
return result;
}
/**
* @sa div(), operator%(), CanonicalForm::operator %=()
**/
CF_INLINE CanonicalForm
mod ( const CanonicalForm & lhs, const CanonicalForm & rhs )
{
CanonicalForm result( lhs );
result.mod( rhs );
return result;
}
#endif
operator/
Rational operator/(const Rational &a, const Rational &b)
Definition GMPrat.cc:422
canonicalform.h
Header for factory's main class CanonicalForm.
div
CF_NO_INLINE FACTORY_PUBLIC CanonicalForm div(const CanonicalForm &, const CanonicalForm &)
mod
CF_NO_INLINE FACTORY_PUBLIC CanonicalForm mod(const CanonicalForm &, const CanonicalForm &)
operator%
CF_NO_INLINE FACTORY_PUBLIC CanonicalForm operator%(const CanonicalForm &, const CanonicalForm &)
CF_INLINE
#define CF_INLINE
Definition canonicalform.h:45
is_imm
int is_imm(const InternalCF *const ptr)
Definition canonicalform.h:65
i
int i
Definition cfEzgcd.cc:132
else
else
Definition cfGcdAlgExt.cc:196
cf
CanonicalForm cf
Definition cfModGcd.cc:4091
cf_assert.h
assertions for Factory
cf_factory.h
Interface to generate InternalCF's over various domains from intrinsic types or mpz_t's.
operator+
CF_INLINE CanonicalForm FACTORY_PUBLIC operator+(const CanonicalForm &lhs, const CanonicalForm &rhs)
CF_INLINE CanonicalForm operator +, -, *, /, % ( const CanonicalForm & lhs, const CanonicalForm & rhs...
Definition cf_inline.cc:503
operator*
CF_INLINE CanonicalForm FACTORY_PUBLIC operator*(const CanonicalForm &lhs, const CanonicalForm &rhs)
Definition cf_inline.cc:524
CFFactory
Definition cf_factory.h:24
CFFactory::basic
static InternalCF * basic(int value)
Definition cf_factory.cc:61
CanonicalForm
factory's main class
Definition canonicalform.h:86
CanonicalForm::value
InternalCF * value
Definition canonicalform.h:88
CanonicalForm::isZero
CF_NO_INLINE bool isZero() const
CanonicalForm::~CanonicalForm
CF_NO_INLINE ~CanonicalForm()
CanonicalForm::CanonicalForm
CF_INLINE CanonicalForm()
CF_INLINE CanonicalForm::CanonicalForm ().
Definition cf_inline.cc:127
CanonicalForm::isOne
CF_NO_INLINE bool isOne() const
CanonicalForm::operator=
CF_NO_INLINE CanonicalForm & operator=(const CanonicalForm &)
InternalCF
virtual class for internal CanonicalForm's
Definition int_cf.h:47
InternalCF::deleteObject
int deleteObject()
Definition int_cf.h:61
Variable
factory's class for variables
Definition factory.h:127
result
return result
Definition facAbsBiFact.cc:76
v
const Variable & v
< [in] a sqrfree bivariate poly
Definition facBivar.h:39
const
#define const
Definition fegetopt.c:39
operator-
fglmVector operator-(const fglmVector &v)
Definition fglmvec.cc:398
FACTORY_PUBLIC
#define FACTORY_PUBLIC
Definition globaldefs.h:25
imm.h
operations on immediates, that is elements of F_p, GF, Z, Q that fit into intrinsic int,...
imm_isone_p
int imm_isone_p(const InternalCF *const ptr)
Definition imm.h:130
imm_isone
int imm_isone(const InternalCF *const ptr)
Definition imm.h:124
imm_iszero
int imm_iszero(const InternalCF *const ptr)
Definition imm.h:145
imm_iszero_gf
int imm_iszero_gf(const InternalCF *const ptr)
Definition imm.h:157
FFMARK
const long FFMARK
Definition imm.h:38
imm_iszero_p
int imm_iszero_p(const InternalCF *const ptr)
Definition imm.h:151
INTMARK
const long INTMARK
Definition imm.h:37
imm_isone_gf
int imm_isone_gf(const InternalCF *const ptr)
Definition imm.h:136
CF_INLINE
#define CF_INLINE
Definition factory.h:208
is_imm
int is_imm(const InternalCF *const ptr)
Definition factory.h:215
int_cf.h
Factory's internal CanonicalForm's.