source: git/factory/cf_inline.cc @ 5e4636

spielwiese
Last change on this file since 5e4636 was 8710ff0, checked in by Martin Lee <martinlee84@…>, 12 years ago
chg: 64bit integers in factory by Adi Popescu
  • Property mode set to 100644
File size: 14.6 KB
Line 
1/* emacs edit mode for this file is -*- C++ -*- */
2
3//{{{ docu
4//
5// cf_inline.cc - definition of configurable inline
6//   `CanonicalForm' methods.
7//
8// Hierarchy: canonicalform
9//
10// Header file: canonicalform.h
11//
12// Developers note:
13// ----------------
14// The central class in Factory is, of course, `CanonicalForm'.
15// Hence it is a quiet reasonable to assume that inlining its
16// most important methods will improve execution speed.  The same
17// holds for some methods of the `CFIterator' class.  Everything
18// on configurable inline `CanonicalForm' methods explained here
19// applies mutatis mutandis to the `CFIterator' methods.
20//
21// However, inlining `CanonicalForm' methods has two major
22// drawbacks:
23//
24// o If `CanonicalForm' methods simply would have been declared
25//   `inline' it would have been necessary to include the
26//   definition of `InternalCF' in `factory.h'.  This would have
27//   been quite a contradiction to the internal nature of the
28//   class.
29//   Hence it seemed desirable to introduce a mechanism to have
30//   both the inlined versions for internal use and compiled
31//   versions for the library.
32//
33// o Second, inlining in most cases leads to larger object code.
34//   E.g., inlining `CanonicalForm::~CanonicalForm()' increases the
35//   object code by approx. 15% without any effect on computation
36//   speed.
37//   Thus another design aim was to keep things configurable.
38//   That is why the methods defined here are called
39//   "configurable inline methods".
40//
41// The low level solution to both problems is the macro
42// `CF_INLINE' which either expands to `inline' or nothing.  The
43// counterpart `CF_NO_INLINE' exists only for convenience, it
44// always expands to nothing.  `CF_INLINE' is set immediately
45// before defining resp. declaring the methods to exclude any
46// esoteric influences from included files.
47//
48// The high level interface is the macro `CF_USE_INLINE'.  If it
49// is defined any header file that uses configurable inline
50// methods defines them to be `inline', otherwise they are
51// defined as ordinary methods.  `CF_USE_INLINE' is defined in
52// `config.h' only.
53//
54// To switch on (off) all configurable inline methods, it is
55// sufficient to define (undefine) `CF_USE_INLINE' in `config.h'.
56// To switch off separate configurable inline methods it is
57// necessary to prefix their declaration in `canonicalform.h' by
58// `CF_NO_INLINE' instead of `CF_INLINE'.  Furthermore, to avoid
59// duplicate symbols at link time, their definition in this file
60// has to be wrapped by an `#ifndef INCL_CF_INLINE_CC'.
61//
62// It turned out that inlining the following methods (and only
63// them) results in the best time to size ratio on Linux and HP
64// machines:
65// o all `CanonicalForm' constructors
66// o the binary `CanonicalForm' operators `+' and `*'
67//
68//}}}
69
70// check whether we are included or translated and
71// define `INCL_CF_INLINE_CC' if we are included
72#ifdef INCL_CANONICALFORM_H
73#define INCL_CF_INLINE_CC
74#endif
75
76#include "config.h"
77
78#include "cf_assert.h"
79
80// temporarily switch off `CF_USE_INLINE' and include
81// `canonicalform.h' if we are being translated.
82// `CF_USE_INLINE_SAVE' is used to save the state of
83// `CF_USE_INLINE'.  It is unset after use.
84#ifndef INCL_CF_INLINE_CC
85#ifdef CF_USE_INLINE
86#define CF_USE_INLINE_SAVE
87#undef CF_USE_INLINE
88#endif
89#include "canonicalform.h"
90#ifdef CF_USE_INLINE_SAVE
91#define CF_USE_INLINE
92#undef CF_USE_INLINE_SAVE
93#endif
94#endif /* ! INCL_CF_INLINE_CC */
95
96// regular include files
97#include "int_cf.h"
98#include "imm.h"
99#include "cf_factory.h"
100
101// set the value of `CF_INLINE' for the following methods and
102// functions
103#if defined( CF_USE_INLINE ) && defined( INCL_CF_INLINE_CC )
104#undef CF_INLINE
105#define CF_INLINE inline
106#else
107#undef CF_INLINE
108#define CF_INLINE
109#endif /* ! defined( CF_USE_INLINE ) && defined( INCL_CF_INLINE_CC ) */
110
111// constructors, destructors, assignment
112//{{{ CF_INLINE CanonicalForm::CanonicalForm ()
113//{{{ docu
114//
115// CanonicalForm() - create the default canonical form.
116//
117// The canonical form is initialized to zero from the current
118// domain.
119//
120//}}}
121CF_INLINE
122CanonicalForm::CanonicalForm ()
123    : value( CFFactory::basic( (long)0 ) )
124{
125}
126//}}}
127
128//{{{ CF_INLINE CanonicalForm::CanonicalForm ( const int i )
129//{{{ docu
130//
131// CanonicalForm() - create a canonical form from an integer.
132//
133// The canonical form is initialized to the "canonical image" of
134// `i' in the current domain.  This is `i' itself for
135// characteristic zero, `i' mod p for finite fields of
136// characteristic p, and `i' mod p^n for prime power domains with
137// p^n elements.
138//
139//}}}
140CF_INLINE
141CanonicalForm::CanonicalForm ( const int i )
142    : value( CFFactory::basic( (long)i ) )
143{
144}
145
146CF_INLINE
147CanonicalForm::CanonicalForm ( const long i )
148    : value( CFFactory::basic( i ) )
149{
150}
151//}}}
152
153//{{{ CF_INLINE CanonicalForm::CanonicalForm ( const CanonicalForm & cf )
154//{{{ docu
155//
156// CanonicalForm() - create a copy of a canonical form.
157//
158// Type info:
159// ----------
160// cf: Anything
161//
162//}}}
163CF_INLINE
164CanonicalForm::CanonicalForm ( const CanonicalForm & cf )
165    : value( is_imm( cf.value ) ? cf.value : cf.value->copyObject() )
166{
167}
168//}}}
169
170//{{{ CF_INLINE CanonicalForm::CanonicalForm ( InternalCF * cf )
171//{{{ docu
172//
173// CanonicalForm() - create a canonical form from a pointer to an
174//   internal canonical form.
175//
176// This constructor is reserved for internal usage.
177//
178// Developers note:
179// ----------------
180// The canonical form gets its value immediately from `cf'.
181// `cf's reference counter is not incremented, so be careful with
182// this constructor.
183//
184//}}}
185CF_INLINE
186CanonicalForm::CanonicalForm ( InternalCF * cf )
187    : value( cf )
188{
189}
190//}}}
191
192//{{{ CF_INLINE CanonicalForm::CanonicalForm ( const Variable & v )
193//{{{ docu
194//
195// CanonicalForm() - create a canonical form from a variable.
196//
197// If `v' is a polynomial variable or an algebraic element the
198// resulting polynomial (or algebraic element) is 1*`v'^1, the
199// one being from the current domain.
200//
201// Variables of level `LEVELBASE' are transformed to one from the
202// current domain.
203//
204// Type info:
205// ----------
206// v: Anything
207//
208//}}}
209CF_INLINE
210CanonicalForm::CanonicalForm ( const Variable & v )
211    : value( CFFactory::poly( v ) )
212{
213}
214//}}}
215
216//{{{ CF_INLINE CanonicalForm::CanonicalForm ( const Variable & v, int e )
217//{{{ docu
218//
219// CanonicalForm() - create a canonical form from a power of a
220//   variable.
221//
222// If `v' is a polynomial variable or an algebraic element the
223// resulting polynomial (or algebraic element) is 1*`v'^`e', the
224// one being from the current domain.  Algebraic elements are
225// reduced modulo their minimal polynomial.
226//
227// Variables of level `LEVELBASE' are transformed to one from the
228// current domain.
229//
230// Type info:
231// ----------
232// v: Anything
233//
234//}}}
235CF_INLINE
236CanonicalForm::CanonicalForm ( const Variable & v, int e )
237    : value( CFFactory::poly( v, e ) )
238{
239    //ASSERT( e > 0, "math error: exponent has to be positive" );
240}
241//}}}
242
243#ifndef INCL_CF_INLINE_CC
244//{{{ CF_INLINE CanonicalForm::~CanonicalForm ()
245//{{{ docu
246//
247// ~CanonicalForm() - delete CO.
248//
249// Type info:
250// ----------
251// CO: Anything
252//
253//}}}
254CF_INLINE
255CanonicalForm::~CanonicalForm ()
256{
257    if ( (! is_imm( value )) && value->deleteObject() )
258        delete value;
259}
260//}}}
261#endif
262
263#ifndef INCL_CF_INLINE_CC
264//{{{ CF_INLINE CanonicalForm & CanonicalForm::operator = ( const CanonicalForm & cf )
265//{{{ docu
266//
267// operator =() - assign `cf' to CO.
268//
269// Type info:
270// ----------
271// CO, cf: Anything
272//
273//}}}
274CF_INLINE CanonicalForm &
275CanonicalForm::operator = ( const CanonicalForm & cf )
276{
277    if ( this != &cf ) {
278        if ( (! is_imm( value )) && value->deleteObject() )
279            delete value;
280        value = (is_imm( cf.value )) ? cf.value : cf.value->copyObject();
281    }
282    return *this;
283}
284//}}}
285
286//{{{ CF_INLINE CanonicalForm & CanonicalForm::operator = ( const int cf )
287//{{{ docu
288//
289// operator =() - assign integer `cf' to CO.
290//
291// `cf' converted to a canonical form as described in the
292// canonical form constructor which creates a canonical form from
293// an integer.
294//
295// Type info:
296// ----------
297// CO: Anything
298//
299// Developers note:
300// ----------------
301// Strictly speaking, this operator is superfluous.  The ordinary
302// assignment operator together with automatic conversion from
303// `int' to `CanonicalForm' would do the job, too.  But this way
304// the common operation of assigning an integer is faster.
305//
306//}}}
307CF_INLINE CanonicalForm &
308CanonicalForm::operator = ( const long cf )
309{
310    if ( (! is_imm( value )) && value->deleteObject() )
311        delete value;
312    value = CFFactory::basic( cf );
313    return *this;
314}
315//}}}
316#endif
317
318// predicates
319#ifndef INCL_CF_INLINE_CC
320//{{{ CF_INLINE bool CanonicalForm::isOne, isZero () const
321//{{{ docu
322//
323// isOne(), isZero() - test whether a `CanonicalForm' equals one
324//   or zero, resp.
325//
326// The predicates `isOne()' and `isZero()' are much faster than
327// the comparison operators.  Furthermore, a test `f.isZero()' is
328// independent from the current domain, whereas an expression
329// `f == 0' is not.
330//
331// Type info:
332// ----------
333// CO: Anything
334//
335// Internal implementation:
336// ------------------------
337// Note that only immediate objects and objects of class
338// `InternalPrimePower' may equal one or zero, resp.
339//
340// imm_isone(), imm_iszero()
341// Trivial.
342//
343// imm_isone_p(), imm_iszero_p()
344// Trivial.
345//
346// imm_isone_gf(), imm_iszero_gf()
347// Use `gf_isone()' and `gf_iszero()', resp., to test whether CO
348// equals zero or one, resp.
349//
350// InternalCF::isOne(), isZero()
351// Always return false.
352//
353// InternalPrimePower::isOne(), isZero()
354// Use `mpz_cpm_ui()' resp. `mpz_sgn()' to check the underlying
355// mpi.
356//
357//}}}
358CF_INLINE bool
359CanonicalForm::isOne () const
360{
361    int what = is_imm( value );
362
363    if ( ! what )
364        return value->isOne();
365    else  if ( what == INTMARK )
366        return imm_isone( value );
367    else if ( what == FFMARK )
368        return imm_isone_p( value );
369    else
370        return imm_isone_gf( value );
371}
372
373CF_INLINE bool
374CanonicalForm::isZero () const
375{
376    int what = is_imm( value );
377
378    if ( what == 0 )
379        return value->isZero();
380    else  if ( what == INTMARK )
381        return imm_iszero( value );
382    else if ( what == FFMARK )
383        return imm_iszero_p( value );
384    else
385        return imm_iszero_gf( value );
386}
387//}}}
388#endif
389
390// arithmetic operators
391#ifndef INCL_CF_INLINE_CC
392//{{{ CF_INLINE CanonicalForm operator - ( const CanonicalForm & cf )
393//{{{ docu
394//
395// operator -() - return additive inverse of `cf'.
396//
397// Returns the additive inverse of `cf'.  One should keep in mind
398// that to negate a canonical form a complete (deep) copy of it
399// has to be created.
400//
401// Type info:
402// ----------
403// cf: CurrentPP
404//
405// In fact, the type is almost `Anything', but it is, e.g., not
406// possible to invert an element from a finite field when the
407// characteristic of the current domain has changed.
408//
409// Internal implementation:
410// ------------------------
411// All internal methods check whether the reference counter
412// equals one.  If so CO is negated in-place.  Otherwise, a new
413// copy of CO is created and negated.
414//
415// imm_neg()
416// Trivial.
417//
418// imm_neg_p()
419// Use `ff_neg()' to negate CO.
420//
421// imm_neg_gf()
422// Use `gf_neg()' to negate CO.
423//
424// InternalInteger::neg()
425// Use `mpz_neg()' to negate the underlying mpi.
426//
427// InternalRational::neg ()
428// Use `mpz_neg()' to negate the denominator.
429//
430// InternalPrimePower::neg()
431// Subtract CO from `primepow' using `mpz_sub'.
432//
433// InternalPoly::neg()
434// If reference counter is one use `negateTermList()' to negate
435// the terms, otherwise create a negated copy using
436// `copyTermList()'.
437//
438//}}}
439CF_INLINE CanonicalForm
440operator - ( const CanonicalForm & cf )
441{
442    CanonicalForm result( cf );
443    int what = is_imm( result.value );
444
445    if ( ! what )
446        result.value = result.value->neg();
447    else  if ( what == INTMARK )
448        result.value = imm_neg( result.value );
449    else if ( what == FFMARK )
450        result.value = imm_neg_p( result.value );
451    else
452        result.value = imm_neg_gf( result.value );
453
454    return result;
455}
456//}}}
457#endif
458
459// binary arithmetic operators and functions
460//{{{ CF_INLINE CanonicalForm operator +, -, *, /, % ( const CanonicalForm & lhs, const CanonicalForm & rhs )
461//{{{ docu
462//
463// operators +, -, *, /, %(), div(), mod() - binary arithmetic
464//   operators.
465//
466// The binary operators have their standard (mathematical)
467// semantics.  As explained for the corresponding arithmetic
468// assignment operators, the operators `/' and `%' return the
469// quotient resp. remainder of (polynomial) division with
470// remainder, whereas `div()' and `mod()' may be used for exact
471// division and term-wise remaindering, resp.
472//
473// It is faster to use the arithmetic assignment operators (e.g.,
474// `f += g;') instead of the binary operators (`f = f+g;' ).
475//
476// Type info:
477// ----------
478// lhs, rhs: CurrentPP
479//
480// There are weaker preconditions for some cases (e.g.,
481// arithmetic operations with elements from Q or Z work in any
482// domain), but type `CurrentPP' is the only one guaranteed to
483// work for all cases.
484//
485// Developers note:
486// ----------------
487// All binary operators have their corresponding `CanonicalForm'
488// assignment operators (e.g., `operator +()' corresponds to
489// `CanonicalForm::operator +=()', `div()' corresponds to
490// `CanonicalForm::div()).
491//
492// And that is how they are implemented, too: Each of the binary
493// operators first creates a copy of `lhs', adds `rhs' to this
494// copy using the assignment operator, and returns the result.
495//
496//}}}
497CF_INLINE CanonicalForm
498operator + ( const CanonicalForm & lhs, const CanonicalForm & rhs )
499{
500    CanonicalForm result( lhs );
501    result += rhs;
502    return result;
503}
504
505#ifndef INCL_CF_INLINE_CC
506CF_INLINE CanonicalForm
507operator - ( const CanonicalForm & lhs, const CanonicalForm & rhs )
508{
509    CanonicalForm result( lhs );
510    result -= rhs;
511    return result;
512}
513#endif
514
515CF_INLINE CanonicalForm
516operator * ( const CanonicalForm & lhs, const CanonicalForm & rhs )
517{
518    CanonicalForm result( lhs );
519    result *= rhs;
520    return result;
521}
522
523#ifndef INCL_CF_INLINE_CC
524CF_INLINE CanonicalForm
525operator / ( const CanonicalForm & lhs, const CanonicalForm & rhs )
526{
527    CanonicalForm result( lhs );
528    result /= rhs;
529    return result;
530}
531
532CF_INLINE CanonicalForm
533operator % ( const CanonicalForm & lhs, const CanonicalForm & rhs )
534{
535    CanonicalForm result( lhs );
536    result %= rhs;
537    return result;
538}
539#endif
540//}}}
541
542#ifndef INCL_CF_INLINE_CC
543//{{{ CF_INLINE CanonicalForm div, mod ( const CanonicalForm & lhs, const CanonicalForm & rhs )
544// docu: see binary operators above
545CF_INLINE CanonicalForm
546div ( const CanonicalForm & lhs, const CanonicalForm & rhs )
547{
548    CanonicalForm result( lhs );
549    result.div( rhs );
550    return result;
551}
552
553CF_INLINE CanonicalForm
554mod ( const CanonicalForm & lhs, const CanonicalForm & rhs )
555{
556    CanonicalForm result( lhs );
557    result.mod( rhs );
558    return result;
559}
560//}}}
561#endif
Note: See TracBrowser for help on using the repository browser.