GiNaCRA
0.6.4
|
00001 /* 00002 * GiNaCRA - GiNaC Real Algebra package 00003 * Copyright (C) 2010-2012 Ulrich Loup, Joachim Redies, Sebastian Junges 00004 * 00005 * This file is part of GiNaCRA. 00006 * 00007 * GiNaCRA is free software: you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation, either version 3 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * GiNaCRA is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with GiNaCRA. If not, see <http://www.gnu.org/licenses/>. 00019 * 00020 */ 00021 00022 00033 #include <assert.h> 00034 00035 #include "OpenInterval.h" 00036 #include "RealAlgebraicNumber.h" 00037 #include "RealAlgebraicNumberIR.h" 00038 #include "RealAlgebraicNumberNR.h" 00039 #include "RealAlgebraicNumberFactory.h" 00040 #include "UnivariatePolynomial.h" 00041 #include "UnivariatePolynomialSet.h" 00042 #include "Constraint.h" 00043 00044 using GiNaC::ex_to; 00045 using GiNaC::is_exactly_a; 00046 using GiNaC::ZERO_SIGN; 00047 using GiNaC::POSITIVE_SIGN; 00048 using GiNaC::NEGATIVE_SIGN; 00049 00050 namespace GiNaCRA 00051 { 00053 // Common // 00055 00056 const GiNaC::numeric abs( const ex& lh ) 00057 { 00058 if( GiNaC::is_exactly_a<numeric>( lh )) 00059 return GiNaC::abs( ex_to<numeric>( lh )); 00060 if( GiNaC::is_a<RealAlgebraicNumberIR>( lh )) 00061 return std::max<GiNaC::numeric>( GiNaC::abs( GiNaC::ex_to<RealAlgebraicNumberIR>( lh ).interval().left() ), 00062 GiNaC::abs( GiNaC::ex_to<RealAlgebraicNumberIR>( lh ).interval().right() )); 00063 return 0; 00064 } 00065 00067 // OpenInterval // 00069 00070 // binary arithmetic operators of OpenInterval 00071 00072 const OpenInterval operator +( const OpenInterval& lh, const OpenInterval& rh ) 00073 { 00074 return lh.add( rh ); 00075 } 00076 00077 const OpenInterval operator -( const OpenInterval& lh, const OpenInterval& rh ) 00078 { 00079 return lh.add( rh.minus() ); 00080 } 00081 00082 const OpenInterval operator *( const OpenInterval& lh, const OpenInterval& rh ) 00083 { 00084 return lh.mul( rh ); 00085 } 00086 00087 // unary arithmetic operators of OpenInterval 00088 00089 const OpenInterval operator -( const OpenInterval& lh ) 00090 { 00091 return lh.minus(); 00092 } 00093 00094 // relational operators 00095 00096 const bool operator ==( const OpenInterval& lh, const OpenInterval& rh ) 00097 { 00098 return lh.isEqual( rh ); 00099 } 00100 00101 const bool operator !=( const OpenInterval& lh, const OpenInterval& rh ) 00102 { 00103 return !lh.isEqual( rh ); 00104 } 00105 00106 const bool operator <=( const OpenInterval& lh, const OpenInterval& rh ) 00107 { 00108 return lh.isLess( rh ); 00109 } 00110 00111 const bool operator >=( const OpenInterval& lh, const OpenInterval& rh ) 00112 { 00113 return lh.isGreater( rh ); 00114 } 00115 00116 // mixed arithmetic operators 00117 00118 const OpenInterval operator +( const OpenInterval& lh, const GiNaC::numeric& rh ) 00119 { 00120 return OpenInterval( lh.left() + rh, lh.right() + rh ); 00121 } 00122 00123 const OpenInterval operator +( const GiNaC::numeric& lh, const OpenInterval& rh ) 00124 { 00125 return OpenInterval( rh.left() + lh, rh.right() + lh ); 00126 } 00127 00128 const OpenInterval operator -( const OpenInterval& lh, const GiNaC::numeric& rh ) 00129 { 00130 return lh + (-rh); 00131 } 00132 00133 const OpenInterval operator -( const GiNaC::numeric& lh, const OpenInterval& rh ) 00134 { 00135 return (-lh) + rh; 00136 } 00137 00138 const OpenInterval operator *( const OpenInterval& lh, const GiNaC::numeric& rh ) 00139 { 00140 numeric l = lh.left() * rh; 00141 numeric r = lh.right() * rh; 00142 numeric min = std::min<numeric>( l, r ); 00143 numeric max = std::max<numeric>( l, r ); 00144 return OpenInterval( min, max ); 00145 } 00146 00147 const OpenInterval operator *( const GiNaC::numeric& lh, const OpenInterval& rh ) 00148 { 00149 return rh * lh; 00150 } 00151 00152 const OpenInterval operator /( const OpenInterval& lh, const GiNaC::numeric& rh ) throw ( overflow_error ) 00153 { 00154 if( rh == 0 ) 00155 throw (overflow_error( "Division by interval containing zero not allowed." )); 00156 numeric l = lh.left() / rh; 00157 numeric r = lh.right() / rh; 00158 numeric min = std::min<numeric>( l, r ); 00159 numeric max = std::max<numeric>( l, r ); 00160 return OpenInterval( min, max ); 00161 } 00162 00163 const OpenInterval operator /( const GiNaC::numeric& lh, const OpenInterval& rh ) throw ( overflow_error ) 00164 { 00165 if( rh.contains( 0 )) 00166 throw (overflow_error( "Division by interval containing zero not allowed." )); 00167 numeric l = lh / rh.left(); 00168 numeric r = lh / rh.right(); 00169 numeric min = std::min<numeric>( l, r ); 00170 numeric max = std::max<numeric>( l, r ); 00171 return OpenInterval( min, max ); 00172 } 00173 00175 // UnivariatePolynomial // 00177 00178 // binary arithmetic operators of UnivariatePolynomial 00179 00180 const UnivariatePolynomial operator +( const UnivariatePolynomial& lh, const UnivariatePolynomial& rh ) 00181 { 00182 return lh.add( rh ); 00183 } 00184 00185 const UnivariatePolynomial operator -( const UnivariatePolynomial& lh, const UnivariatePolynomial& rh ) 00186 { 00187 return lh.sub( rh ); 00188 } 00189 00190 const UnivariatePolynomial operator *( const UnivariatePolynomial& lh, const UnivariatePolynomial& rh ) 00191 { 00192 return lh.mul( rh ); 00193 } 00194 00195 const UnivariatePolynomial operator /( const UnivariatePolynomial& lh, const UnivariatePolynomial& rh ) 00196 { 00197 return lh.quo( rh ); 00198 } 00199 00200 const UnivariatePolynomial operator %( const UnivariatePolynomial& lh, const UnivariatePolynomial& rh ) 00201 { 00202 return lh.rem( rh ); 00203 } 00204 00205 // binary arithmetic operators of RationalUnivariatePolynomial 00206 00207 const RationalUnivariatePolynomial operator +( const RationalUnivariatePolynomial& lh, const RationalUnivariatePolynomial& rh ) 00208 { 00209 return RationalUnivariatePolynomial( static_cast<ex>(lh)+static_cast<ex>(rh), lh.variable() ); 00210 } 00211 00212 const RationalUnivariatePolynomial operator -( const RationalUnivariatePolynomial& lh, const RationalUnivariatePolynomial& rh ) 00213 { 00214 return RationalUnivariatePolynomial( static_cast<ex>(lh)-static_cast<ex>(rh), lh.variable() ); 00215 } 00216 00217 const RationalUnivariatePolynomial operator *( const RationalUnivariatePolynomial& lh, const RationalUnivariatePolynomial& rh ) 00218 { 00219 return RationalUnivariatePolynomial( static_cast<ex>(lh)*static_cast<ex>(rh), lh.variable() ); 00220 } 00221 00222 const RationalUnivariatePolynomial operator /( const RationalUnivariatePolynomial& lh, const RationalUnivariatePolynomial& rh ) 00223 { 00224 return lh.quo( rh ); 00225 } 00226 00227 const RationalUnivariatePolynomial operator %( const RationalUnivariatePolynomial& lh, const RationalUnivariatePolynomial& rh ) 00228 { 00229 return lh.rem( rh ); 00230 // return RationalUnivariatePolynomial( GiNaC::rem( *this, o, mVariable ), mVariable ); 00231 } 00232 00233 // unary arithmetic operators of UnivariatePolynomial 00234 00235 const UnivariatePolynomial operator -( const UnivariatePolynomial& lh ) 00236 { 00237 return UnivariatePolynomial( -static_cast<ex>(lh), lh.variable(), lh.enabledPolynomialCheck() ); 00238 } 00239 00240 const RationalUnivariatePolynomial operator -( const RationalUnivariatePolynomial& lh ) 00241 { 00242 return RationalUnivariatePolynomial( -static_cast<ex>(lh), lh.variable() ); 00243 } 00244 00245 // relational operators of UnivariatePolynomial 00246 00247 const bool operator ==( const UnivariatePolynomial& lh, const UnivariatePolynomial& rh ) 00248 { 00249 return lh.isEqual( rh ); 00250 } 00251 00252 const bool operator !=( const UnivariatePolynomial& lh, const UnivariatePolynomial& rh ) 00253 { 00254 return !lh.isEqual( rh ); 00255 } 00256 00258 // UnivariatePolynomialSet // 00260 00261 std::ostream& operator <<( std::ostream& os, const UnivariatePolynomialSet& s ) 00262 { 00263 os << "{"; 00264 for( UnivariatePolynomialSet::const_iterator i = s.begin(); i != s.end(); ++i ) 00265 os << " " << static_cast<UnivariatePolynomial>(*i); 00266 os << " }"; 00267 return os; 00268 } 00269 00271 // RealAlgebraicNumberIR // 00273 00274 // binary arithmetic operators 00275 00276 RealAlgebraicNumberIR& operator +( RealAlgebraicNumberIR& lh, RealAlgebraicNumberIR& rh ) 00277 { 00278 return lh.add( rh ); 00279 } 00280 00281 RealAlgebraicNumberIR& operator -( RealAlgebraicNumberIR& lh, RealAlgebraicNumberIR& rh ) 00282 { 00283 RealAlgebraicNumberIR rhMinus = rh.minus(); 00284 return lh.add( rhMinus ); 00285 } 00286 00287 RealAlgebraicNumberIR& operator *( RealAlgebraicNumberIR& lh, RealAlgebraicNumberIR& rh ) 00288 { 00289 return lh.mul( rh ); 00290 } 00291 00292 RealAlgebraicNumberIR& operator /( RealAlgebraicNumberIR& lh, RealAlgebraicNumberIR& rh ) 00293 { 00294 RealAlgebraicNumberIR rhInverse = rh.inverse(); 00295 return lh.mul( rhInverse ); 00296 } 00297 00298 RealAlgebraicNumberIR& operator ^( RealAlgebraicNumberIR& base, int exponent ) 00299 { 00300 return base.pow( exponent ); 00301 } 00302 00303 // unary arithmetic operators 00304 00305 RealAlgebraicNumberIR& operator -( RealAlgebraicNumberIR& lh ) 00306 { 00307 return lh.minus(); 00308 } 00309 00310 // relational operators 00311 00312 const bool operator ==( RealAlgebraicNumberIR& lh, RealAlgebraicNumberIR& rh ) 00313 { 00314 return lh.isEqual( rh ); 00315 } 00316 00317 const bool operator ==( const RealAlgebraicNumberIR& lh, const RealAlgebraicNumberIR& rh ) 00318 { 00319 RealAlgebraicNumberIR lhRef = lh; 00320 RealAlgebraicNumberIR rhRef = rh; 00321 return lhRef.isEqual( rhRef ); 00322 } 00323 00324 const bool operator !=( RealAlgebraicNumberIR& lh, RealAlgebraicNumberIR& rh ) 00325 { 00326 return !lh.isEqual( rh ); 00327 } 00328 00329 const bool operator <( RealAlgebraicNumberIR& lh, RealAlgebraicNumberIR& rh ) 00330 { 00331 return lh.isLess( rh ); 00332 } 00333 00334 const bool operator >( RealAlgebraicNumberIR& lh, RealAlgebraicNumberIR& rh ) 00335 { 00336 return !lh.isEqual( rh ) &&!lh.isLessWhileUnequal( rh ); 00337 } 00338 00339 const bool operator <=( RealAlgebraicNumberIR& lh, RealAlgebraicNumberIR& rh ) 00340 { 00341 return lh.isEqual( rh ) || lh.isLessWhileUnequal( rh ); 00342 } 00343 00344 const bool operator >=( RealAlgebraicNumberIR& lh, RealAlgebraicNumberIR& rh ) 00345 { 00346 return !lh.isLess( rh ); 00347 } 00348 00349 // mixed arithmetic operators 00350 00351 RealAlgebraicNumberIR& operator +( const GiNaC::numeric& lh, RealAlgebraicNumberIR& rh ) 00352 { 00353 RationalUnivariatePolynomial p( rh.polynomial().subs( rh.polynomial().variable() == (rh.polynomial().variable() - lh) ), 00354 rh.polynomial().variable() ); 00355 while( RationalUnivariatePolynomial::countRealRoots( p, rh.interval() + lh ) != 1 ) // refine rh until a unique number representation is found 00356 rh.refine(); 00357 return *new RealAlgebraicNumberIR( p, rh.interval() + lh ); 00358 } 00359 00360 RealAlgebraicNumberIR& operator +( RealAlgebraicNumberIR& lh, const GiNaC::numeric& rh ) 00361 { 00362 RationalUnivariatePolynomial p( lh.polynomial().subs( lh.polynomial().variable() == (lh.polynomial().variable() - rh) ), 00363 lh.polynomial().variable() ); 00364 while( RationalUnivariatePolynomial::countRealRoots( p, rh + lh.interval() ) != 1 ) // refine rh until a unique number representation is found 00365 lh.refine(); 00366 return *new RealAlgebraicNumberIR( p, rh + lh.interval() ); 00367 } 00368 00369 RealAlgebraicNumberIR& operator -( const GiNaC::numeric& lh, RealAlgebraicNumberIR& rh ) 00370 { 00371 RationalUnivariatePolynomial p( rh.polynomial().subs( rh.polynomial().variable() == (rh.polynomial().variable() + lh) ), 00372 rh.polynomial().variable() ); 00373 while( RationalUnivariatePolynomial::countRealRoots( p, rh.interval() - lh ) != 1 ) // refine rh until a unique number representation is found 00374 rh.refine(); 00375 return *new RealAlgebraicNumberIR( p, rh.interval() - lh ); 00376 } 00377 00378 RealAlgebraicNumberIR& operator -( RealAlgebraicNumberIR& lh, const GiNaC::numeric& rh ) 00379 { 00380 RationalUnivariatePolynomial p( lh.polynomial().subs( lh.polynomial().variable() == (lh.polynomial().variable() + rh) ), 00381 lh.polynomial().variable() ); 00382 while( RationalUnivariatePolynomial::countRealRoots( p, rh - lh.interval() ) != 1 ) // refine rh until a unique number representation is found 00383 lh.refine(); 00384 return *new RealAlgebraicNumberIR( p, rh - lh.interval() ); 00385 } 00386 00387 RealAlgebraicNumberIR& operator *( const GiNaC::numeric& lh, RealAlgebraicNumberIR& rh ) 00388 { 00389 if( lh == 0 ) 00390 return *RealAlgebraicNumberIR::zero( rh.polynomial().variable() ); 00391 RationalUnivariatePolynomial p( rh.polynomial().subs( rh.polynomial().variable() == (rh.polynomial().variable() * lh.inverse())), 00392 rh.polynomial().variable() ); 00393 while( RationalUnivariatePolynomial::countRealRoots( p, rh.interval() * lh ) != 1 ) // refine rh until a unique number representation is found 00394 rh.refine(); 00395 return *new RealAlgebraicNumberIR( p, rh.interval() * lh ); 00396 } 00397 00398 RealAlgebraicNumberIR& operator *( RealAlgebraicNumberIR& lh, const GiNaC::numeric& rh ) 00399 { 00400 if( rh == 0 ) 00401 return *RealAlgebraicNumberIR::zero( lh.polynomial().variable() ); 00402 RationalUnivariatePolynomial p( lh.polynomial().subs( lh.polynomial().variable() == (lh.polynomial().variable() * rh.inverse())), 00403 lh.polynomial().variable() ); 00404 while( RationalUnivariatePolynomial::countRealRoots( p, rh * lh.interval() ) != 1 ) // refine rh until a unique number representation is found 00405 lh.refine(); 00406 return *new RealAlgebraicNumberIR( p, rh * lh.interval() ); 00407 } 00408 00409 RealAlgebraicNumberIR& operator /( const GiNaC::numeric& lh, RealAlgebraicNumberIR& rh ) 00410 { 00411 return lh * rh.inverse(); 00412 } 00413 00414 RealAlgebraicNumberIR& operator /( RealAlgebraicNumberIR& lh, const GiNaC::numeric& rh ) 00415 { 00416 return lh * rh.inverse(); 00417 } 00418 00420 // RealAlgebraicNumber // 00422 00423 // basic operator 00424 00425 RealAlgebraicNumberPtr binaryOperator( const RealAlgebraicNumberPtr& lh, const RealAlgebraicNumberPtr& rh, RealAlgebraicNumberIR&( *opIRIR )( RealAlgebraicNumberIR&, RealAlgebraicNumberIR& ), RealAlgebraicNumberIR&( *opIRNR )( RealAlgebraicNumberIR&, const numeric&), const numeric( *opNRNR )(const numeric&, const numeric&) ) 00426 { 00427 RealAlgebraicNumberIRPtr lhIR = std::tr1::dynamic_pointer_cast<RealAlgebraicNumberIR>( lh ); 00428 RealAlgebraicNumberIRPtr rhIR = std::tr1::dynamic_pointer_cast<RealAlgebraicNumberIR>( rh ); 00429 if( lhIR == 0 ) 00430 { 00431 RealAlgebraicNumberNRPtr lhNR = std::tr1::dynamic_pointer_cast<RealAlgebraicNumberNR>( lh ); 00432 if( rhIR == 0 ) 00433 { 00434 RealAlgebraicNumberNRPtr rhNR = std::tr1::dynamic_pointer_cast<RealAlgebraicNumberNR>( rh ); 00435 return RealAlgebraicNumberPtr( new RealAlgebraicNumberNR( (*opNRNR)( *lhNR, *rhNR ))); 00436 } 00437 else 00438 { 00439 RealAlgebraicNumberIR sum = (*opIRNR)( *rhIR, *lhNR ); 00440 if( sum.isNumeric() ) 00441 return RealAlgebraicNumberPtr( new RealAlgebraicNumberNR( sum.value() )); 00442 return RealAlgebraicNumberPtr( new RealAlgebraicNumberIR( sum )); 00443 } 00444 } 00445 if( rhIR == 0 ) 00446 { 00447 RealAlgebraicNumberNRPtr rhNR = std::tr1::dynamic_pointer_cast<RealAlgebraicNumberNR>( rh ); 00448 RealAlgebraicNumberIR sum = (*opIRNR)( *lhIR, *rhNR ); 00449 if( sum.isNumeric() ) 00450 return RealAlgebraicNumberPtr( new RealAlgebraicNumberNR( sum.value() )); 00451 return RealAlgebraicNumberPtr( new RealAlgebraicNumberIR( sum )); 00452 } 00453 else 00454 { 00455 RealAlgebraicNumberIR sum = (*opIRIR)( *lhIR, *rhIR ); 00456 if( sum.isNumeric() ) 00457 return RealAlgebraicNumberPtr( new RealAlgebraicNumberNR( sum.value() )); 00458 return RealAlgebraicNumberPtr( new RealAlgebraicNumberIR( sum )); 00459 } 00460 } 00461 00462 // binary arithmetic operators 00463 00464 RealAlgebraicNumberPtr operator +( const RealAlgebraicNumberPtr& lh, const RealAlgebraicNumberPtr& rh ) 00465 { 00466 return binaryOperator( lh, rh, operator +, operator +, GiNaC::operator + ); 00467 } 00468 00469 RealAlgebraicNumberPtr operator -( const RealAlgebraicNumberPtr& lh, const RealAlgebraicNumberPtr& rh ) 00470 { 00471 return binaryOperator( lh, -rh, operator +, operator +, GiNaC::operator + ); 00472 } 00473 00474 RealAlgebraicNumberPtr operator *( const RealAlgebraicNumberPtr& lh, const RealAlgebraicNumberPtr& rh ) 00475 { 00476 return binaryOperator( lh, rh, operator *, operator *, GiNaC::operator * ); 00477 } 00478 00479 RealAlgebraicNumberPtr operator /( const RealAlgebraicNumberPtr& lh, const RealAlgebraicNumberPtr& rh ) 00480 { 00481 return binaryOperator( lh, rh, operator /, operator /, GiNaC::operator / ); 00482 } 00483 00484 RealAlgebraicNumberPtr operator ^( const RealAlgebraicNumberPtr& base, int exponent ) 00485 { 00486 RealAlgebraicNumberIRPtr baseIR = std::tr1::dynamic_pointer_cast<RealAlgebraicNumberIR>( base ); 00487 if( baseIR == 0 ) 00488 return RealAlgebraicNumberPtr( new RealAlgebraicNumberNR( 00489 std::tr1::dynamic_pointer_cast<RealAlgebraicNumberNR>( base )->power( exponent ))); 00490 if( baseIR->isNumeric() ) 00491 return RealAlgebraicNumberPtr( new RealAlgebraicNumberNR( baseIR->value().power( exponent ))); 00492 return RealAlgebraicNumberPtr( new RealAlgebraicNumberIR( baseIR->pow( exponent ))); 00493 } 00494 00495 // unary arithmetic operators 00496 00497 RealAlgebraicNumberPtr operator -( const RealAlgebraicNumberPtr& lh ) 00498 { 00499 RealAlgebraicNumberIRPtr lhIR = std::tr1::dynamic_pointer_cast<RealAlgebraicNumberIR>( lh ); 00500 if( lhIR == 0 ) 00501 return RealAlgebraicNumberPtr( new RealAlgebraicNumberNR( -*std::tr1::dynamic_pointer_cast<RealAlgebraicNumberNR>( lh ))); 00502 if( lhIR->isNumeric() ) 00503 return RealAlgebraicNumberPtr( new RealAlgebraicNumberNR( -lhIR->value() )); 00504 return RealAlgebraicNumberPtr( new RealAlgebraicNumberIR( -*lhIR )); 00505 } 00506 00507 // relational operators 00508 00509 const bool operator ==( const RealAlgebraicNumberPtr& a, const RealAlgebraicNumberPtr& b ) 00510 { 00511 return RealAlgebraicNumberFactory::equal( a, b ); 00512 } 00513 00514 const bool operator !=( const RealAlgebraicNumberPtr& a, const RealAlgebraicNumberPtr& b ) 00515 { 00516 return !RealAlgebraicNumberFactory::equal( a, b ); 00517 } 00518 00519 const bool operator <( const RealAlgebraicNumberPtr& a, const RealAlgebraicNumberPtr& b ) 00520 { 00521 return RealAlgebraicNumberFactory::less( a, b ); 00522 } 00523 00524 std::ostream& operator <<( std::ostream& os, const RealAlgebraicNumberPtr& a ) 00525 { 00526 print( a, os ); 00527 return os; 00528 } 00529 00530 // workaround until operator<< works 00531 00532 void print( const RealAlgebraicNumberPtr& a, std::ostream& os ) 00533 { 00534 RealAlgebraicNumberIRPtr irA = std::tr1::dynamic_pointer_cast<RealAlgebraicNumberIR>( a ); 00535 RealAlgebraicNumberNRPtr nrA = std::tr1::dynamic_pointer_cast<RealAlgebraicNumberNR>( a ); 00536 if( irA != 0 ) 00537 std::cout << *irA; 00538 else if( nrA != 0 ) 00539 std::cout << static_cast<RealAlgebraicNumberNR>(*nrA); 00540 00541 else 00542 std::cout << "NaN"; 00543 // assert( false ); // This case should never occur! If it still occurs, there might be a segfault somewhere. 00544 } 00545 00547 // RealAlgebraicPoint // 00549 00550 std::ostream& operator <<( std::ostream& os, const RealAlgebraicPoint& r ) 00551 { 00552 os << "("; 00553 for( RealAlgebraicPoint::const_iterator i = r.begin(); i != r.end(); ++i ) 00554 print( *i, os << " " ); 00555 os << " )"; 00556 return os; 00557 } 00558 00560 // Constraint // 00562 00563 // relational operators 00564 00565 const bool operator ==( const Constraint& a, const Constraint& b ) 00566 { 00567 return a.poly() == b.poly() && a.sign() == b.sign(); // Vriables do not need to be checked since they are uniquely defined in GiNaC and therefore checked by the ex check. 00568 } 00569 00570 // streaming operators 00571 00572 std::ostream& operator <<( std::ostream& os, const Constraint& a ) 00573 { 00574 GiNaC::sign s = a.sign(); 00575 os << a.poly() << (s == ZERO_SIGN ? " = 0" : s == POSITIVE_SIGN ? " > 0" : " < 0"); 00576 vector<symbol> variables = a.variables(); 00577 os << "(" << variables.front(); 00578 for( unsigned i = 1; i != variables.size(); ++i ) 00579 os << ", " << variables[i]; 00580 return os << ")"; 00581 } 00582 00583 } // namespace GiNaC 00584