2 * File: PolynomialFactorizationPair.tpp
3 * Author: Florian Corzilius
5 * Created on September 5, 2014, 3:57 PM
10 #include "PolynomialFactorizationPair.h"
12 #include "FactorizedPolynomial.h"
13 #include <carl-logging/carl-logging.h>
14 #include <carl-arith/poly/umvpoly/functions/Definiteness.h>
15 #include <carl-arith/poly/umvpoly/functions/GCD.h>
20 std::string factorizationToString( const Factorization<P>& _factorization, bool _infix, bool _friendlyVarNames )
22 if( _factorization.empty() )
31 for( auto polyExpPair = _factorization.begin(); polyExpPair != _factorization.end(); ++polyExpPair )
33 if( polyExpPair != _factorization.begin() )
35 assert( polyExpPair->second > 0 );
36 result += "(" + polyExpPair->first.toString( true, _friendlyVarNames ) + ")";
37 if( polyExpPair->second > 1 )
40 s << polyExpPair->second;
41 result += "^" + s.str();
47 if( _factorization.size() == 1 && _factorization.begin()->second == 1 )
49 return _factorization.begin()->first.toString( false, _friendlyVarNames );
52 for( auto polyExpPair = _factorization.begin(); polyExpPair != _factorization.end(); ++polyExpPair )
54 assert( polyExpPair->second > 0 );
55 for( size_t i = 0; i < polyExpPair->second; ++i )
56 result += " " + polyExpPair->first.toString( false, _friendlyVarNames );
65 std::ostream& operator<<( std::ostream& _out, const Factorization<P>& _factorization )
67 _out << factorizationToString( _factorization );
72 bool factorizationsEqual( const Factorization<P>& _factorizationA, const Factorization<P>& _factorizationB )
74 auto iterA = _factorizationA.begin();
75 auto iterB = _factorizationB.begin();
76 while( iterA != _factorizationA.end() && iterB != _factorizationB.end() )
78 if( iterA->second != iterB->second || !(iterA->first == iterB->first) )
82 return iterA == _factorizationA.end() && iterB == _factorizationB.end();
86 PolynomialFactorizationPair<P>::PolynomialFactorizationPair( Factorization<P>&& _factorization, P* _polynomial ):
89 mFactorization( std::move( _factorization ) ),
90 mpPolynomial( _polynomial ),
93 if ( mpPolynomial == nullptr )
95 if ( mFactorization.size() == 1 )
97 // No factorization -> set polynomial
98 assert( existsFactorization( mFactorization.begin()->first ) );
99 mpPolynomial = new P( carl::pow(*mFactorization.begin()->first.content().mpPolynomial, mFactorization.begin()->second ) );
100 assert( mpPolynomial != nullptr );
105 if ( is_one(*mpPolynomial) )
107 assert( mFactorization.size() == 0);
108 mpPolynomial = nullptr;
113 assert( mpPolynomial == nullptr || carl::is_one(mpPolynomial->coprime_factor()) );
114 assert( mpPolynomial == nullptr || mFactorization.empty() || assertFactorization() );
120 PolynomialFactorizationPair<P>::~PolynomialFactorizationPair()
126 void PolynomialFactorizationPair<P>::rehash() const
128 std::lock_guard<std::recursive_mutex> lock( mMutex );
129 if( mpPolynomial == nullptr )
131 assert( mFactorization.empty() || mFactorization.size() > 1 );
133 for( auto polyExpPair = mFactorization.begin(); polyExpPair != mFactorization.end(); ++polyExpPair )
135 mHash = (mHash << 5) | (mHash >> (sizeof(size_t)*8 - 5));
136 mHash ^= std::hash<FactorizedPolynomial<P>>()( polyExpPair->first );
137 mHash = (mHash << 5) | (mHash >> (sizeof(size_t)*8 - 5));
138 mHash ^= polyExpPair->second;
143 mHash = std::hash<P>()( *mpPolynomial );
148 bool operator==( const PolynomialFactorizationPair<P>& _polyFactA, const PolynomialFactorizationPair<P>& _polyFactB )
150 if( &_polyFactA == &_polyFactB )
153 //if ( _polyFactA.mHash != _polyFactB.mHash )
155 std::lock_guard<std::recursive_mutex> lockA( _polyFactA.mMutex );
156 std::lock_guard<std::recursive_mutex> lockB( _polyFactB.mMutex );
157 if( _polyFactA.mpPolynomial != nullptr && _polyFactB.mpPolynomial != nullptr )
159 return *_polyFactA.mpPolynomial == *_polyFactB.mpPolynomial;
163 if( factorizationsEqual( _polyFactA.factorization(), _polyFactB.factorization() ) )
167 // There is no way around this );
168 if( _polyFactA.mpPolynomial == nullptr )
169 _polyFactA.mpPolynomial = new P( computePolynomial( _polyFactA.factorization() ) );
170 if( _polyFactB.mpPolynomial == nullptr )
171 _polyFactB.mpPolynomial = new P( computePolynomial( _polyFactB.factorization() ) );
172 return *_polyFactA.mpPolynomial == *_polyFactB.mpPolynomial;
178 bool operator<( const PolynomialFactorizationPair<P>& _polyFactA, const PolynomialFactorizationPair<P>& _polyFactB )
180 if( &_polyFactA == &_polyFactB )
182 std::lock_guard<std::recursive_mutex> lockA( _polyFactA.mMutex );
183 std::lock_guard<std::recursive_mutex> lockB( _polyFactB.mMutex );
184 if( _polyFactA.mpPolynomial != nullptr && _polyFactB.mpPolynomial != nullptr )
186 return *_polyFactA.mpPolynomial < *_polyFactB.mpPolynomial;
190 auto iterA = _polyFactA.factorization().begin();
191 auto iterB = _polyFactB.factorization().begin();
192 while( iterA != _polyFactA.factorization().end() && iterB != _polyFactB.factorization().end() )
194 if( iterA->first < iterB->first )
198 else if( iterA->first == iterB->first )
200 if( iterA->second < iterB->second )
204 else if( iterA->second > iterB->second )
215 return iterA == _polyFactA.factorization().end();
220 bool canBeUpdated( const PolynomialFactorizationPair<P>& _toUpdate, const PolynomialFactorizationPair<P>& _updateWith )
222 if( &_toUpdate == &_updateWith )
224 std::lock_guard<std::recursive_mutex> lockA( _toUpdate.mMutex );
225 std::lock_guard<std::recursive_mutex> lockB( _updateWith.mMutex );
226 assert( _toUpdate.hash() == _updateWith.hash() && _toUpdate == _updateWith );
227 if( _toUpdate.mpPolynomial == nullptr && _updateWith.mpPolynomial != nullptr )
229 assert( _updateWith.mpPolynomial == nullptr || (*_toUpdate.mpPolynomial) == (*_updateWith.mpPolynomial) );
230 return !_updateWith.factorization().empty() && !factorizationsEqual( _toUpdate.factorization(), _updateWith.factorization() );
234 void update( PolynomialFactorizationPair<P>& _toUpdate, PolynomialFactorizationPair<P>& _updateWith )
236 assert( canBeUpdated( _toUpdate, _updateWith ) ); // This assertion only ensures efficient use this method.
237 assert( &_toUpdate != &_updateWith );
238 assert( _toUpdate.mpPolynomial == nullptr || _updateWith.mpPolynomial == nullptr || *_toUpdate.mpPolynomial == *_updateWith.mpPolynomial );
239 std::lock_guard<std::recursive_mutex> lockA( _toUpdate.mMutex );
240 std::lock_guard<std::recursive_mutex> lockB( _updateWith.mMutex );
241 if( _toUpdate.mpPolynomial == nullptr && _updateWith.mpPolynomial != nullptr )
242 _toUpdate.mpPolynomial = _updateWith.mpPolynomial;
243 // The factorization of the PolynomialFactorizationPair to update which can be empty, if constructed freshly by a polynomial.
244 if( _toUpdate.factorizedTrivially() && !_updateWith.factorizedTrivially() )
246 _toUpdate.mFactorization = _updateWith.mFactorization;
248 if( !factorizationsEqual( _toUpdate.factorization(), _updateWith.factorization() ) )
250 // Calculating the gcd refines both factorizations to the same factorization
251 bool refineA = false;
252 bool refineB = false;
253 Factorization<P> restA, restB;
254 typename P::CoeffType c( 0 );
255 gcd( _toUpdate, _updateWith, restA, restB, c, refineA, refineB );
256 assert( c == typename P::CoeffType( 0 ) || c == typename P::CoeffType( 1 ) );
261 P computePolynomial( const Factorization<P>& _factorization )
264 for (auto ft = _factorization.begin(); ft != _factorization.end(); ft++ )
266 result *= carl::pow(computePolynomial( ft->first ), ft->second );
272 P computePolynomial( const PolynomialFactorizationPair<P>& _pfPair )
274 if( _pfPair.mpPolynomial != nullptr )
275 return *_pfPair.mpPolynomial;
276 return computePolynomial( _pfPair.factorization() );
280 typename P::CoeffType PolynomialFactorizationPair<P>::flattenFactorization() const
282 typename P::CoeffType result( 0 );
283 if ( factorizedTrivially() )
287 std::lock_guard<std::recursive_mutex> lock( mMutex );
288 for( auto ft = mFactorization.begin(); ft != mFactorization.end(); )
290 if( ft->first.content().factorizedTrivially() )
292 if ( ft->first.coefficient() != 1 )
294 if( result == typename P::CoeffType( 0 ) )
295 result = typename P::CoeffType( 1 );
296 carl::exponent e = ft->second;
298 result *= carl::pow( ft->first.coefficient(), e );
299 ft->first.setCoefficient( 1 );
305 // Update factorization
306 if( result == typename P::CoeffType( 0 ) )
307 result = typename P::CoeffType( 1 );
308 const Factorization<P>& partFactorization = ft->first.factorization();
309 assert( carl::is_positive( ft->first.coefficient() ) );
310 carl::exponent e = ft->second;
312 result *= carl::pow( ft->first.coefficient(), e );
314 for( auto partFactor = partFactorization.begin(); partFactor != partFactorization.end(); partFactor++ )
316 mFactorization.insert( std::pair<FactorizedPolynomial<P>, carl::exponent>( partFactor->first, partFactor->second * e ) );
318 ft = mFactorization.erase(ft);
321 assert( assertFactorization() );
326 bool PolynomialFactorizationPair<P>::isIrreducible() const
328 if ( mIrreducible != -1 )
329 return mIrreducible == 1;
331 assert( mpPolynomial != nullptr );
332 if ( mpPolynomial->is_linear() )
337 Definiteness definiteness = carl::definiteness(*mpPolynomial);
338 if ( definiteness == Definiteness::POSITIVE || definiteness == Definiteness::NEGATIVE )
348 void PolynomialFactorizationPair<P>::setNewFactors( const FactorizedPolynomial<P>& _fpolyA, carl::exponent exponentA, const FactorizedPolynomial<P>& _fpolyB, carl::exponent exponentB ) const
350 assert( mFactorization.size() == 1 );
351 assert( factorizedTrivially() );
352 assert( !_fpolyA.is_one() );
353 assert( !_fpolyB.is_one() );
354 //assert( carl::is_one(_fpolyA.coefficient()) );
355 //assert( carl::is_one(_fpolyB.coefficient()) );
356 assert( exponentA > 0 );
357 assert( exponentB > 0 );
358 mFactorization.clear();
359 if( _fpolyA == _fpolyB )
361 mFactorization.insert ( std::pair<FactorizedPolynomial<P>, carl::exponent>( _fpolyA, exponentA+exponentB ) );
365 mFactorization.insert ( std::pair<FactorizedPolynomial<P>, carl::exponent>( _fpolyA, exponentA ) );
366 mFactorization.insert ( std::pair<FactorizedPolynomial<P>, carl::exponent>( _fpolyB, exponentB ) );
368 assert( mpPolynomial != nullptr );
369 assert( *mpPolynomial == computePolynomial( mFactorization ) );
370 assert( assertFactorization() );
374 Factorization<P> gcd( const PolynomialFactorizationPair<P>& _pfPairA, const PolynomialFactorizationPair<P>& _pfPairB, Factorization<P>& _restA, Factorization<P>& _restB, typename P::CoeffType& _coeff, bool& _pfPairARefined, bool& _pfPairBRefined )
376 CARL_LOG_DEBUG( "carl.core.factorizedpolynomial", "****************************************************" );
377 CARL_LOG_DEBUG( "carl.core.factorizedpolynomial", "Compute GCD (internal) of " << _pfPairA << " and " << _pfPairB );
378 if( &_pfPairA == &_pfPairB )
379 return _pfPairA.factorization();
380 std::lock_guard<std::recursive_mutex> lockA( _pfPairA.mMutex );
381 std::lock_guard<std::recursive_mutex> lockB( _pfPairB.mMutex );
382 _coeff = typename P::CoeffType( 1 );
383 _pfPairARefined = false;
384 _pfPairBRefined = false;
387 // First flatten the factorizations of both polynomials
388 typename P::CoeffType cA = _pfPairA.flattenFactorization();
389 if( cA != typename P::CoeffType( 0 ) )
391 // Refinement took place -> set flag which indicates to update the first given factorized polynomial in its cache
392 _pfPairARefined = true;
395 typename P::CoeffType cB = _pfPairB.flattenFactorization();
396 if( cB != typename P::CoeffType( 0 ) )
398 // Refinement took place -> set flag which indicates to update the second given factorized polynomial in its cache
399 _pfPairBRefined = true;
402 // Factorization<P> factorizationA = _pfPairA.mFactorization;
403 // Factorization<P> factorizationB = _pfPairB.mFactorization;
404 // Factorization<P> result;
405 Factorization<P> factorizationA;
406 Factorization<P> factorizationB;
407 Factorization<P> result = commonDivisor( _pfPairA.mFactorization, _pfPairB.mFactorization, factorizationA, factorizationB );
408 while ( !factorizationA.empty() )
410 //Consider first factor in currently not checked factorization of A
411 FactorizedPolynomial<P> factorA = factorizationA.begin()->first;
412 carl::exponent exponentA = factorizationA.begin()->second;
413 factorizationA.erase( factorizationA.begin() );
414 bool breaked = false;
415 while ( !factorA.is_one() && !factorizationB.empty() )
417 // If the first factor is has a non trivial factorization -> flatten (this could be introduced during this loop even if we flatted beforehand)
418 const Factorization<P>& currentFactorizationA = factorA.factorization();
419 if( currentFactorizationA.size() != 1 )
421 factorizationA.insert( currentFactorizationA.begin(), currentFactorizationA.end() );
424 } else if ( currentFactorizationA.begin()->second > 1 ) {
425 // Polynomial has exponent > 1
426 exponentA *= currentFactorizationA.begin()->second;
427 factorA = currentFactorizationA.begin()->first;
429 // Take the second factor
430 FactorizedPolynomial<P> factorB = factorizationB.begin()->first;
431 carl::exponent exponentB = factorizationB.begin()->second;
432 factorizationB.erase( factorizationB.begin() );
433 // If the second factor is has a non trivial factorization -> flatten (this could be introduced during this loop even if we flatted beforehand)
434 const Factorization<P>& currentFactorizationB = factorB.factorization();
435 if( currentFactorizationB.size() != 1 )
437 factorizationB.insert( currentFactorizationB.begin(), currentFactorizationB.end() );
439 } else if ( currentFactorizationB.begin()->second > 1 ) {
440 // Polynomial has exponent > 1
441 exponentB *= currentFactorizationB.begin()->second;
442 factorB = currentFactorizationB.begin()->first;
444 CARL_LOG_DEBUG( "carl.core.factorizedpolynomial", "" );
445 CARL_LOG_DEBUG( "carl.core.factorizedpolynomial", "####################################################" );
446 CARL_LOG_DEBUG( "carl.core.factorizedpolynomial", "For first factorization: " );
447 CARL_LOG_DEBUG( "carl.core.factorizedpolynomial", " current factor: (" << factorA << ")^" << exponentA );
448 CARL_LOG_DEBUG( "carl.core.factorizedpolynomial", " open remainder: " << factorizationA );
449 CARL_LOG_DEBUG( "carl.core.factorizedpolynomial", " closed remainder: " << _restA );
450 CARL_LOG_DEBUG( "carl.core.factorizedpolynomial", "For second factorization: " );
451 CARL_LOG_DEBUG( "carl.core.factorizedpolynomial", " current factor: (" << factorB << ")^" << exponentB );
452 CARL_LOG_DEBUG( "carl.core.factorizedpolynomial", " open remainder: " << factorizationB );
453 CARL_LOG_DEBUG( "carl.core.factorizedpolynomial", " closed remainder: " << _restB );
454 CARL_LOG_DEBUG( "carl.core.factorizedpolynomial", "already found gcd is:" << result );
455 CARL_LOG_DEBUG( "carl.core.factorizedpolynomial", "" );
456 // Check if the factors are equal (even if we removed equal factor by commonDivisor() beforehand, common factors could be introduced during this loop)
457 if( factorA == factorB )
459 //Common factor found
460 carl::exponent exponentCommon = exponentA < exponentB ? exponentA : exponentB;
461 result.insert( std::pair<FactorizedPolynomial<P>, carl::exponent>( factorA, exponentCommon ) );
462 CARL_LOG_DEBUG( "carl.core.factorizedpolynomial", __LINE__ << ": add (" << factorA << ")^" << exponentCommon << " to gcd: " << result );
463 if (exponentA > exponentCommon)
465 factorizationA.insert( std::pair<FactorizedPolynomial<P>, carl::exponent>( factorA, exponentA-exponentCommon ) );
466 CARL_LOG_DEBUG( "carl.core.factorizedpolynomial", __LINE__ << ": add (" << factorA << ")^" << (exponentA-exponentCommon) << " to first open remainder: " << factorizationA );
468 if (exponentB > exponentCommon)
470 //Ignore FactorB as it has no remaining common factor with current FactorB
471 _restB.insert( std::pair<FactorizedPolynomial<P>, carl::exponent>( factorB, exponentB-exponentCommon ) );
472 CARL_LOG_DEBUG( "carl.core.factorizedpolynomial", __LINE__ << ": add (" << factorB << ")^" << (exponentB-exponentCommon) << " to second open remainder: " << _restB );
474 factorA = FactorizedPolynomial<P>( carl::constant_one<typename P::CoeffType>::get() );
475 CARL_LOG_DEBUG( "carl.core.factorizedpolynomial", __LINE__ << ": set current factor to: (1)^1" );
479 P polGCD, polA, polB;
480 assert( existsFactorization( factorA ) );
481 assert( existsFactorization( factorB ) );
482 if ( factorA.content().isIrreducible() && factorB.content().isIrreducible() )
486 //Compute GCD of factors
487 assert( factorA.content().mpPolynomial != nullptr );
488 assert( factorB.content().mpPolynomial != nullptr );
489 polA = *factorA.content().mpPolynomial;
490 polB = *factorB.content().mpPolynomial;
491 polGCD = carl::gcd( polA, polB );
492 if (carl::is_negative(polGCD.lcoeff())) {
495 CARL_LOG_DEBUG( "carl.core.factorizedpolynomial", __LINE__ << ": GCD of " << polA << " and " << polB << ": " << polGCD);
500 //Ignore FactorB as it has no common factor with current FactorA
501 _restB.insert( std::pair<FactorizedPolynomial<P>, carl::exponent>( factorB, exponentB ) );
502 CARL_LOG_DEBUG( "carl.core.factorizedpolynomial", __LINE__ << ": add (" << factorB << ")^" << exponentB << " to second finished remainder: " << _restB );
507 P remainA = carl::quotient(polA, polGCD );
508 P remainB = carl::quotient(polB, polGCD );
509 carl::exponent exponentCommon = exponentA < exponentB ? exponentA : exponentB;
510 std::shared_ptr<Cache<PolynomialFactorizationPair<P>>> cache = factorA.pCache();
511 //Set new part of GCD
512 FactorizedPolynomial<P> gcdResult( polGCD, cache );
513 result.insert( std::pair<FactorizedPolynomial<P>, carl::exponent>( gcdResult, exponentCommon ) );
514 CARL_LOG_DEBUG( "carl.core.factorizedpolynomial", __LINE__ << ": add (" << gcdResult << ")^" << exponentCommon << " to gcd: " << result );
517 if ( exponentA > exponentCommon )
519 exponentA -= exponentCommon;
523 factorA = FactorizedPolynomial<P>( carl::constant_one<typename P::CoeffType>::get() );
524 CARL_LOG_DEBUG( "carl.core.factorizedpolynomial", __LINE__ << ": set current factor to: (1)^1" );
529 //Set new factorization
530 FactorizedPolynomial<P> polRemainA( remainA, cache );
531 factorA.content().setNewFactors( gcdResult, 1, polRemainA, 1 );
532 _pfPairARefined = true;
533 factorA = polRemainA;
534 //Add remaining factorization
535 if (exponentA > exponentCommon)
537 factorizationA.insert( std::pair<FactorizedPolynomial<P>, carl::exponent>( gcdResult, exponentA-exponentCommon ) );
538 CARL_LOG_DEBUG( "carl.core.factorizedpolynomial", __LINE__ << ": add (" << gcdResult << ")^" << (exponentA-exponentCommon) << " to first open remainder: " << factorizationA );
542 //Part of FactorB remains
543 if ( exponentB > exponentCommon )
545 factorizationB.insert( std::pair<FactorizedPolynomial<P>, carl::exponent>( gcdResult, exponentB-exponentCommon) );
546 CARL_LOG_DEBUG( "carl.core.factorizedpolynomial", __LINE__ << ": add (" << gcdResult << ")^" << (exponentB-exponentCommon) << " to second open remainder: " << factorizationB );
549 if (!is_one(remainB))
551 //Set new factorization
552 FactorizedPolynomial<P> polRemainB( remainB, cache );
553 factorB.content().setNewFactors( gcdResult, 1, polRemainB, 1 );
554 _pfPairBRefined = true;
555 //Ignore remaining factorization as it has no common factor with FactorA anymore
556 factorizationB.insert( std::pair<FactorizedPolynomial<P>, carl::exponent>( polRemainB, exponentB) );
557 CARL_LOG_DEBUG( "carl.core.factorizedpolynomial", __LINE__ << ": add (" << polRemainB << ")^" << exponentB << " to second open remainder: " << _restB );
561 } //End of inner while
564 //Insert remaining factorA into rest
565 if( !factorA.is_one() )
567 _restA.insert( std::pair<FactorizedPolynomial<P>, carl::exponent>( factorA, exponentA ) );
568 CARL_LOG_DEBUG( "carl.core.factorizedpolynomial", __LINE__ << ": add (" << factorA << ")^" << exponentA << " to first closed remainder: " << _restA );
570 //Reset factorizationB
571 factorizationB.insert( _restB.begin(), _restB.end() );
573 CARL_LOG_DEBUG( "carl.core.factorizedpolynomial", __LINE__ << ": shift second closed remainder to second open remainder: " << factorizationB );
574 } //End of outer while
575 _restB = factorizationB;
576 cA = _pfPairA.flattenFactorization();
577 if( cA != typename P::CoeffType( 0 ) )
579 _pfPairARefined = true;
582 cB = _pfPairB.flattenFactorization();
583 if( cB != typename P::CoeffType( 0 ) )
585 _pfPairBRefined = true;
588 assert( carl::is_one(_coeff) );
590 assert( _pfPairA.assertFactorization() );
591 assert( _pfPairB.assertFactorization() );
592 CARL_LOG_DEBUG( "carl.core.factorizedpolynomial", "GCD (internal) of " << _pfPairA << " and " << _pfPairB << ": " << result << " with rests " << _restA << " and " << _restB );
593 assert( computePolynomial( result ) * computePolynomial( _restA ) == computePolynomial( _pfPairA ) );
594 assert( computePolynomial( result ) * computePolynomial( _restB ) == computePolynomial( _pfPairB ) );
595 assert( carl::is_one(carl::gcd( computePolynomial( _restA ), computePolynomial( _restB ))));
600 Factors<FactorizedPolynomial<P>> factor( const PolynomialFactorizationPair<P>& _pfPair, const typename P::CoeffType& _coeff )
602 typename P::CoeffType constantFactor = _coeff;
603 bool allFactorsIrreducible = false;
604 Factors<FactorizedPolynomial<P>> result;
605 if( !_pfPair.mFactorization.empty() )
607 _pfPair.mMutex.lock();
608 while( !allFactorsIrreducible )
610 _pfPair.flattenFactorization();
611 allFactorsIrreducible = true;
612 for( auto ft = _pfPair.mFactorization.begin(); ft != _pfPair.mFactorization.end(); )
614 assert( existsFactorization( ft->first ) );
615 if( ft->first.content().isIrreducible() )
621 assert( ft->first.factorization().size() == 1 );
622 assert( carl::is_one( ft->first.coefficient() ) );
623 carl::exponent e = ft->second;
625 Factors<typename FactorizedPolynomial<P>::PolyType> factorFactorization = carl::factor( ft->first.polynomial() );
626 Factorization<P> refinement;
627 for( const auto& pt : factorFactorization )
629 if( pt.first.is_constant() )
630 constantFactor *= pt.first.constant_part();
633 FactorizedPolynomial<P> fp(pt.first, ft->first.pCache());
634 constantFactor *= carl::pow( fp.coefficient(), pt.second );
635 refinement.insert( std::pair<FactorizedPolynomial<P>, carl::exponent>( fp.coprime_coefficients(), pt.second ) );
638 ft = _pfPair.mFactorization.erase(ft);
640 for( auto partFactor = refinement.begin(); partFactor != refinement.end(); partFactor++ )
642 assert( existsFactorization( partFactor->first ) );
643 auto insertResult = _pfPair.mFactorization.insert( std::pair<FactorizedPolynomial<P>, carl::exponent>( partFactor->first, partFactor->second * e ) );
644 if( insertResult.first->first.factorization().size() > 1 ) // Note that factorization() takes care about the flattening
646 assert( insertResult.first->first.content().mIrreducible == 0 );
647 allFactorsIrreducible = false;
651 insertResult.first->first.content().mIrreducible = 1;
657 _pfPair.mMutex.unlock();
658 for( auto ft = _pfPair.mFactorization.begin(); ft != _pfPair.mFactorization.end(); ft++ )
660 result.insert( std::pair<FactorizedPolynomial<P>, carl::exponent>( ft->first, ft->second ) );
663 result.insert( std::pair<FactorizedPolynomial<P>, unsigned>( FactorizedPolynomial<P>(constantFactor), 1 ) );
667 template <typename P>
668 std::ostream& operator<<(std::ostream& _out, const PolynomialFactorizationPair<P>& _pfPair)
670 if (_pfPair.factorizedTrivially()) {
671 return _out << _pfPair.polynomial();
673 return _out << factorizationToString(_pfPair.factorization());