[babc50] | 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 | |
---|
[e4fe2b] | 76 | #include "config.h" |
---|
[babc50] | 77 | |
---|
[650f2d8] | 78 | #include "cf_assert.h" |
---|
[babc50] | 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 | //}}} |
---|
| 121 | CF_INLINE |
---|
| 122 | CanonicalForm::CanonicalForm () |
---|
| 123 | : value( CFFactory::basic( (int)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 | //}}} |
---|
| 140 | CF_INLINE |
---|
| 141 | CanonicalForm::CanonicalForm ( const int i ) |
---|
| 142 | : value( CFFactory::basic( i ) ) |
---|
| 143 | { |
---|
| 144 | } |
---|
| 145 | //}}} |
---|
| 146 | |
---|
| 147 | //{{{ CF_INLINE CanonicalForm::CanonicalForm ( const CanonicalForm & cf ) |
---|
| 148 | //{{{ docu |
---|
| 149 | // |
---|
| 150 | // CanonicalForm() - create a copy of a canonical form. |
---|
| 151 | // |
---|
| 152 | // Type info: |
---|
| 153 | // ---------- |
---|
| 154 | // cf: Anything |
---|
| 155 | // |
---|
| 156 | //}}} |
---|
| 157 | CF_INLINE |
---|
| 158 | CanonicalForm::CanonicalForm ( const CanonicalForm & cf ) |
---|
| 159 | : value( is_imm( cf.value ) ? cf.value : cf.value->copyObject() ) |
---|
| 160 | { |
---|
| 161 | } |
---|
| 162 | //}}} |
---|
| 163 | |
---|
| 164 | //{{{ CF_INLINE CanonicalForm::CanonicalForm ( InternalCF * cf ) |
---|
| 165 | //{{{ docu |
---|
| 166 | // |
---|
| 167 | // CanonicalForm() - create a canonical form from a pointer to an |
---|
| 168 | // internal canonical form. |
---|
| 169 | // |
---|
| 170 | // This constructor is reserved for internal usage. |
---|
| 171 | // |
---|
| 172 | // Developers note: |
---|
| 173 | // ---------------- |
---|
| 174 | // The canonical form gets its value immediately from `cf'. |
---|
| 175 | // `cf's reference counter is not incremented, so be careful with |
---|
| 176 | // this constructor. |
---|
| 177 | // |
---|
| 178 | //}}} |
---|
| 179 | CF_INLINE |
---|
| 180 | CanonicalForm::CanonicalForm ( InternalCF * cf ) |
---|
| 181 | : value( cf ) |
---|
| 182 | { |
---|
| 183 | } |
---|
| 184 | //}}} |
---|
| 185 | |
---|
| 186 | //{{{ CF_INLINE CanonicalForm::CanonicalForm ( const Variable & v ) |
---|
| 187 | //{{{ docu |
---|
| 188 | // |
---|
| 189 | // CanonicalForm() - create a canonical form from a variable. |
---|
| 190 | // |
---|
| 191 | // If `v' is a polynomial variable or an algebraic element the |
---|
| 192 | // resulting polynomial (or algebraic element) is 1*`v'^1, the |
---|
| 193 | // one being from the current domain. |
---|
| 194 | // |
---|
| 195 | // Variables of level `LEVELBASE' are transformed to one from the |
---|
| 196 | // current domain. |
---|
| 197 | // |
---|
| 198 | // Type info: |
---|
| 199 | // ---------- |
---|
| 200 | // v: Anything |
---|
| 201 | // |
---|
| 202 | //}}} |
---|
| 203 | CF_INLINE |
---|
| 204 | CanonicalForm::CanonicalForm ( const Variable & v ) |
---|
| 205 | : value( CFFactory::poly( v ) ) |
---|
| 206 | { |
---|
| 207 | } |
---|
| 208 | //}}} |
---|
| 209 | |
---|
| 210 | //{{{ CF_INLINE CanonicalForm::CanonicalForm ( const Variable & v, int e ) |
---|
| 211 | //{{{ docu |
---|
| 212 | // |
---|
| 213 | // CanonicalForm() - create a canonical form from a power of a |
---|
| 214 | // variable. |
---|
| 215 | // |
---|
| 216 | // If `v' is a polynomial variable or an algebraic element the |
---|
| 217 | // resulting polynomial (or algebraic element) is 1*`v'^`e', the |
---|
| 218 | // one being from the current domain. Algebraic elements are |
---|
| 219 | // reduced modulo their minimal polynomial. |
---|
| 220 | // |
---|
| 221 | // Variables of level `LEVELBASE' are transformed to one from the |
---|
| 222 | // current domain. |
---|
| 223 | // |
---|
| 224 | // Type info: |
---|
| 225 | // ---------- |
---|
| 226 | // v: Anything |
---|
| 227 | // |
---|
| 228 | //}}} |
---|
| 229 | CF_INLINE |
---|
| 230 | CanonicalForm::CanonicalForm ( const Variable & v, int e ) |
---|
| 231 | : value( CFFactory::poly( v, e ) ) |
---|
| 232 | { |
---|
[57daf8] | 233 | //ASSERT( e > 0, "math error: exponent has to be positive" ); |
---|
[babc50] | 234 | } |
---|
| 235 | //}}} |
---|
| 236 | |
---|
| 237 | #ifndef INCL_CF_INLINE_CC |
---|
| 238 | //{{{ CF_INLINE CanonicalForm::~CanonicalForm () |
---|
| 239 | //{{{ docu |
---|
| 240 | // |
---|
| 241 | // ~CanonicalForm() - delete CO. |
---|
| 242 | // |
---|
| 243 | // Type info: |
---|
| 244 | // ---------- |
---|
| 245 | // CO: Anything |
---|
| 246 | // |
---|
| 247 | //}}} |
---|
| 248 | CF_INLINE |
---|
| 249 | CanonicalForm::~CanonicalForm () |
---|
| 250 | { |
---|
| 251 | if ( (! is_imm( value )) && value->deleteObject() ) |
---|
[806c18] | 252 | delete value; |
---|
[babc50] | 253 | } |
---|
| 254 | //}}} |
---|
| 255 | #endif |
---|
| 256 | |
---|
| 257 | #ifndef INCL_CF_INLINE_CC |
---|
| 258 | //{{{ CF_INLINE CanonicalForm & CanonicalForm::operator = ( const CanonicalForm & cf ) |
---|
| 259 | //{{{ docu |
---|
| 260 | // |
---|
| 261 | // operator =() - assign `cf' to CO. |
---|
| 262 | // |
---|
| 263 | // Type info: |
---|
| 264 | // ---------- |
---|
| 265 | // CO, cf: Anything |
---|
| 266 | // |
---|
| 267 | //}}} |
---|
| 268 | CF_INLINE CanonicalForm & |
---|
| 269 | CanonicalForm::operator = ( const CanonicalForm & cf ) |
---|
| 270 | { |
---|
| 271 | if ( this != &cf ) { |
---|
[806c18] | 272 | if ( (! is_imm( value )) && value->deleteObject() ) |
---|
| 273 | delete value; |
---|
| 274 | value = (is_imm( cf.value )) ? cf.value : cf.value->copyObject(); |
---|
[babc50] | 275 | } |
---|
| 276 | return *this; |
---|
| 277 | } |
---|
| 278 | //}}} |
---|
| 279 | |
---|
| 280 | //{{{ CF_INLINE CanonicalForm & CanonicalForm::operator = ( const int cf ) |
---|
| 281 | //{{{ docu |
---|
| 282 | // |
---|
| 283 | // operator =() - assign integer `cf' to CO. |
---|
| 284 | // |
---|
| 285 | // `cf' converted to a canonical form as described in the |
---|
| 286 | // canonical form constructor which creates a canonical form from |
---|
| 287 | // an integer. |
---|
| 288 | // |
---|
| 289 | // Type info: |
---|
| 290 | // ---------- |
---|
| 291 | // CO: Anything |
---|
| 292 | // |
---|
| 293 | // Developers note: |
---|
| 294 | // ---------------- |
---|
| 295 | // Strictly speaking, this operator is superfluous. The ordinary |
---|
| 296 | // assignment operator together with automatic conversion from |
---|
| 297 | // `int' to `CanonicalForm' would do the job, too. But this way |
---|
| 298 | // the common operation of assigning an integer is faster. |
---|
| 299 | // |
---|
| 300 | //}}} |
---|
| 301 | CF_INLINE CanonicalForm & |
---|
| 302 | CanonicalForm::operator = ( const int cf ) |
---|
| 303 | { |
---|
| 304 | if ( (! is_imm( value )) && value->deleteObject() ) |
---|
[806c18] | 305 | delete value; |
---|
[babc50] | 306 | value = CFFactory::basic( cf ); |
---|
| 307 | return *this; |
---|
| 308 | } |
---|
| 309 | //}}} |
---|
| 310 | #endif |
---|
| 311 | |
---|
| 312 | // predicates |
---|
| 313 | #ifndef INCL_CF_INLINE_CC |
---|
| 314 | //{{{ CF_INLINE bool CanonicalForm::isOne, isZero () const |
---|
| 315 | //{{{ docu |
---|
| 316 | // |
---|
| 317 | // isOne(), isZero() - test whether a `CanonicalForm' equals one |
---|
| 318 | // or zero, resp. |
---|
| 319 | // |
---|
| 320 | // The predicates `isOne()' and `isZero()' are much faster than |
---|
| 321 | // the comparison operators. Furthermore, a test `f.isZero()' is |
---|
| 322 | // independent from the current domain, whereas an expression |
---|
| 323 | // `f == 0' is not. |
---|
| 324 | // |
---|
| 325 | // Type info: |
---|
| 326 | // ---------- |
---|
| 327 | // CO: Anything |
---|
| 328 | // |
---|
| 329 | // Internal implementation: |
---|
| 330 | // ------------------------ |
---|
| 331 | // Note that only immediate objects and objects of class |
---|
| 332 | // `InternalPrimePower' may equal one or zero, resp. |
---|
| 333 | // |
---|
| 334 | // imm_isone(), imm_iszero() |
---|
| 335 | // Trivial. |
---|
| 336 | // |
---|
| 337 | // imm_isone_p(), imm_iszero_p() |
---|
| 338 | // Trivial. |
---|
| 339 | // |
---|
| 340 | // imm_isone_gf(), imm_iszero_gf() |
---|
| 341 | // Use `gf_isone()' and `gf_iszero()', resp., to test whether CO |
---|
| 342 | // equals zero or one, resp. |
---|
| 343 | // |
---|
| 344 | // InternalCF::isOne(), isZero() |
---|
| 345 | // Always return false. |
---|
| 346 | // |
---|
| 347 | // InternalPrimePower::isOne(), isZero() |
---|
| 348 | // Use `mpz_cpm_ui()' resp. `mpz_sgn()' to check the underlying |
---|
| 349 | // mpi. |
---|
[806c18] | 350 | // |
---|
[babc50] | 351 | //}}} |
---|
| 352 | CF_INLINE bool |
---|
| 353 | CanonicalForm::isOne () const |
---|
| 354 | { |
---|
| 355 | int what = is_imm( value ); |
---|
| 356 | |
---|
| 357 | if ( ! what ) |
---|
[806c18] | 358 | return value->isOne(); |
---|
[babc50] | 359 | else if ( what == INTMARK ) |
---|
[806c18] | 360 | return imm_isone( value ); |
---|
[babc50] | 361 | else if ( what == FFMARK ) |
---|
[806c18] | 362 | return imm_isone_p( value ); |
---|
[babc50] | 363 | else |
---|
[806c18] | 364 | return imm_isone_gf( value ); |
---|
[babc50] | 365 | } |
---|
| 366 | |
---|
| 367 | CF_INLINE bool |
---|
| 368 | CanonicalForm::isZero () const |
---|
| 369 | { |
---|
| 370 | int what = is_imm( value ); |
---|
| 371 | |
---|
[aa5055] | 372 | if ( what == 0 ) |
---|
[806c18] | 373 | return value->isZero(); |
---|
[babc50] | 374 | else if ( what == INTMARK ) |
---|
[806c18] | 375 | return imm_iszero( value ); |
---|
[babc50] | 376 | else if ( what == FFMARK ) |
---|
[806c18] | 377 | return imm_iszero_p( value ); |
---|
[babc50] | 378 | else |
---|
[806c18] | 379 | return imm_iszero_gf( value ); |
---|
[babc50] | 380 | } |
---|
| 381 | //}}} |
---|
| 382 | #endif |
---|
| 383 | |
---|
| 384 | // arithmetic operators |
---|
| 385 | #ifndef INCL_CF_INLINE_CC |
---|
| 386 | //{{{ CF_INLINE CanonicalForm operator - ( const CanonicalForm & cf ) |
---|
| 387 | //{{{ docu |
---|
| 388 | // |
---|
| 389 | // operator -() - return additive inverse of `cf'. |
---|
| 390 | // |
---|
| 391 | // Returns the additive inverse of `cf'. One should keep in mind |
---|
| 392 | // that to negate a canonical form a complete (deep) copy of it |
---|
| 393 | // has to be created. |
---|
| 394 | // |
---|
[806c18] | 395 | // Type info: |
---|
[babc50] | 396 | // ---------- |
---|
| 397 | // cf: CurrentPP |
---|
| 398 | // |
---|
| 399 | // In fact, the type is almost `Anything', but it is, e.g., not |
---|
| 400 | // possible to invert an element from a finite field when the |
---|
| 401 | // characteristic of the current domain has changed. |
---|
| 402 | // |
---|
| 403 | // Internal implementation: |
---|
| 404 | // ------------------------ |
---|
| 405 | // All internal methods check whether the reference counter |
---|
| 406 | // equals one. If so CO is negated in-place. Otherwise, a new |
---|
| 407 | // copy of CO is created and negated. |
---|
| 408 | // |
---|
| 409 | // imm_neg() |
---|
| 410 | // Trivial. |
---|
| 411 | // |
---|
| 412 | // imm_neg_p() |
---|
| 413 | // Use `ff_neg()' to negate CO. |
---|
| 414 | // |
---|
| 415 | // imm_neg_gf() |
---|
| 416 | // Use `gf_neg()' to negate CO. |
---|
| 417 | // |
---|
| 418 | // InternalInteger::neg() |
---|
| 419 | // Use `mpz_neg()' to negate the underlying mpi. |
---|
| 420 | // |
---|
| 421 | // InternalRational::neg () |
---|
| 422 | // Use `mpz_neg()' to negate the denominator. |
---|
| 423 | // |
---|
| 424 | // InternalPrimePower::neg() |
---|
| 425 | // Subtract CO from `primepow' using `mpz_sub'. |
---|
| 426 | // |
---|
| 427 | // InternalPoly::neg() |
---|
| 428 | // If reference counter is one use `negateTermList()' to negate |
---|
| 429 | // the terms, otherwise create a negated copy using |
---|
| 430 | // `copyTermList()'. |
---|
| 431 | // |
---|
| 432 | //}}} |
---|
| 433 | CF_INLINE CanonicalForm |
---|
| 434 | operator - ( const CanonicalForm & cf ) |
---|
| 435 | { |
---|
| 436 | CanonicalForm result( cf ); |
---|
| 437 | int what = is_imm( result.value ); |
---|
| 438 | |
---|
| 439 | if ( ! what ) |
---|
[806c18] | 440 | result.value = result.value->neg(); |
---|
[babc50] | 441 | else if ( what == INTMARK ) |
---|
[806c18] | 442 | result.value = imm_neg( result.value ); |
---|
[babc50] | 443 | else if ( what == FFMARK ) |
---|
[806c18] | 444 | result.value = imm_neg_p( result.value ); |
---|
[babc50] | 445 | else |
---|
[806c18] | 446 | result.value = imm_neg_gf( result.value ); |
---|
[babc50] | 447 | |
---|
| 448 | return result; |
---|
| 449 | } |
---|
| 450 | //}}} |
---|
| 451 | #endif |
---|
| 452 | |
---|
| 453 | // binary arithmetic operators and functions |
---|
| 454 | //{{{ CF_INLINE CanonicalForm operator +, -, *, /, % ( const CanonicalForm & lhs, const CanonicalForm & rhs ) |
---|
| 455 | //{{{ docu |
---|
| 456 | // |
---|
| 457 | // operators +, -, *, /, %(), div(), mod() - binary arithmetic |
---|
| 458 | // operators. |
---|
| 459 | // |
---|
| 460 | // The binary operators have their standard (mathematical) |
---|
| 461 | // semantics. As explained for the corresponding arithmetic |
---|
| 462 | // assignment operators, the operators `/' and `%' return the |
---|
| 463 | // quotient resp. remainder of (polynomial) division with |
---|
| 464 | // remainder, whereas `div()' and `mod()' may be used for exact |
---|
| 465 | // division and term-wise remaindering, resp. |
---|
| 466 | // |
---|
| 467 | // It is faster to use the arithmetic assignment operators (e.g., |
---|
| 468 | // `f += g;') instead of the binary operators (`f = f+g;' ). |
---|
| 469 | // |
---|
| 470 | // Type info: |
---|
| 471 | // ---------- |
---|
| 472 | // lhs, rhs: CurrentPP |
---|
| 473 | // |
---|
| 474 | // There are weaker preconditions for some cases (e.g., |
---|
| 475 | // arithmetic operations with elements from Q or Z work in any |
---|
| 476 | // domain), but type `CurrentPP' is the only one guaranteed to |
---|
| 477 | // work for all cases. |
---|
| 478 | // |
---|
| 479 | // Developers note: |
---|
| 480 | // ---------------- |
---|
| 481 | // All binary operators have their corresponding `CanonicalForm' |
---|
| 482 | // assignment operators (e.g., `operator +()' corresponds to |
---|
| 483 | // `CanonicalForm::operator +=()', `div()' corresponds to |
---|
| 484 | // `CanonicalForm::div()). |
---|
| 485 | // |
---|
| 486 | // And that is how they are implemented, too: Each of the binary |
---|
| 487 | // operators first creates a copy of `lhs', adds `rhs' to this |
---|
| 488 | // copy using the assignment operator, and returns the result. |
---|
| 489 | // |
---|
| 490 | //}}} |
---|
| 491 | CF_INLINE CanonicalForm |
---|
| 492 | operator + ( const CanonicalForm & lhs, const CanonicalForm & rhs ) |
---|
| 493 | { |
---|
| 494 | CanonicalForm result( lhs ); |
---|
| 495 | result += rhs; |
---|
| 496 | return result; |
---|
| 497 | } |
---|
| 498 | |
---|
| 499 | #ifndef INCL_CF_INLINE_CC |
---|
| 500 | CF_INLINE CanonicalForm |
---|
| 501 | operator - ( const CanonicalForm & lhs, const CanonicalForm & rhs ) |
---|
| 502 | { |
---|
| 503 | CanonicalForm result( lhs ); |
---|
| 504 | result -= rhs; |
---|
| 505 | return result; |
---|
| 506 | } |
---|
| 507 | #endif |
---|
| 508 | |
---|
| 509 | CF_INLINE CanonicalForm |
---|
| 510 | operator * ( const CanonicalForm & lhs, const CanonicalForm & rhs ) |
---|
| 511 | { |
---|
| 512 | CanonicalForm result( lhs ); |
---|
| 513 | result *= rhs; |
---|
| 514 | return result; |
---|
| 515 | } |
---|
| 516 | |
---|
| 517 | #ifndef INCL_CF_INLINE_CC |
---|
| 518 | CF_INLINE CanonicalForm |
---|
| 519 | operator / ( const CanonicalForm & lhs, const CanonicalForm & rhs ) |
---|
| 520 | { |
---|
| 521 | CanonicalForm result( lhs ); |
---|
| 522 | result /= rhs; |
---|
| 523 | return result; |
---|
| 524 | } |
---|
| 525 | |
---|
| 526 | CF_INLINE CanonicalForm |
---|
| 527 | operator % ( const CanonicalForm & lhs, const CanonicalForm & rhs ) |
---|
| 528 | { |
---|
| 529 | CanonicalForm result( lhs ); |
---|
| 530 | result %= rhs; |
---|
| 531 | return result; |
---|
| 532 | } |
---|
| 533 | #endif |
---|
| 534 | //}}} |
---|
| 535 | |
---|
| 536 | #ifndef INCL_CF_INLINE_CC |
---|
| 537 | //{{{ CF_INLINE CanonicalForm div, mod ( const CanonicalForm & lhs, const CanonicalForm & rhs ) |
---|
| 538 | // docu: see binary operators above |
---|
| 539 | CF_INLINE CanonicalForm |
---|
| 540 | div ( const CanonicalForm & lhs, const CanonicalForm & rhs ) |
---|
| 541 | { |
---|
| 542 | CanonicalForm result( lhs ); |
---|
| 543 | result.div( rhs ); |
---|
| 544 | return result; |
---|
| 545 | } |
---|
| 546 | |
---|
| 547 | CF_INLINE CanonicalForm |
---|
| 548 | mod ( const CanonicalForm & lhs, const CanonicalForm & rhs ) |
---|
| 549 | { |
---|
| 550 | CanonicalForm result( lhs ); |
---|
| 551 | result.mod( rhs ); |
---|
| 552 | return result; |
---|
| 553 | } |
---|
| 554 | //}}} |
---|
| 555 | #endif |
---|