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