BWAPI
|
00001 // Copyright (c) 2005 Stanford University (USA). 00002 // All rights reserved. 00003 // 00004 // This file is part of CGAL (www.cgal.org); you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public License as 00006 // published by the Free Software Foundation; version 2.1 of the License. 00007 // See the file LICENSE.LGPL distributed with CGAL. 00008 // 00009 // Licensees holding a valid commercial license may use this file in 00010 // accordance with the commercial license agreement provided with the software. 00011 // 00012 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 00013 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00014 // 00015 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Kinetic_data_structures/include/CGAL/Polynomial/internal/Simple_interval_root.h $ 00016 // $Id: Simple_interval_root.h 45637 2008-09-18 15:41:45Z hemmer $ 00017 // 00018 // 00019 // Author(s) : Daniel Russel <drussel@alumni.princeton.edu> 00020 00021 #ifndef CGAL_POLYNOMIAL_SIMPLE_INTERVAL_ROOT_H 00022 #define CGAL_POLYNOMIAL_SIMPLE_INTERVAL_ROOT_H 00023 #include <CGAL/Polynomial/basic.h> 00024 #include <CGAL/Real_embeddable_traits.h> 00025 #include <vector> 00026 CGAL_POLYNOMIAL_BEGIN_INTERNAL_NAMESPACE; 00027 00029 00033 template <class Traits> 00034 class Simple_interval_root 00035 { 00036 typedef Simple_interval_root<Traits> This; 00037 00038 00039 typedef enum Fields {INVALID= 4,UP=1, INF=2} Type_fields; 00040 typedef unsigned char Type; 00041 typedef typename Traits::Function Polynomial; 00042 typedef typename Traits::FT NT; 00043 public: 00044 Simple_interval_root(){ 00045 set_type(INVALID); 00046 CGAL_Polynomial_assertion(is_null()); 00047 } 00048 00049 Simple_interval_root(double nt): function_(0), interval_(nt,nt) { 00050 if (std::numeric_limits<double>::has_infinity && (nt == std::numeric_limits<double>::infinity() 00051 || -nt == std::numeric_limits<double>::infinity())) { 00052 if (nt == std::numeric_limits<double>::infinity() ) { 00053 set_type(INF|UP); 00054 } 00055 else { 00056 set_type(INF); 00057 } 00058 } else { 00059 set_type(0); 00060 ii_= std::make_pair(NT(nt),NT(nt)); 00061 } 00062 audit(); 00063 compute_approximation(); 00064 } 00065 00066 Simple_interval_root(const Simple_interval_root<Traits> &o):ii_(o.ii_), type_(o.type_), 00067 function_(o.function_), 00068 kernel_(o.kernel_), interval_(o.interval_) 00069 #ifndef NDEBUG 00070 , approximation_(o.approximation_) 00071 #endif 00072 { 00073 00074 } 00075 00076 /*Simple_interval_root(Type t): type_(t) { 00077 audit(); 00078 compute_approximation(); 00079 };*/ 00080 00082 Simple_interval_root(const NT &nt): ii_(std::make_pair(nt,nt)), function_(0), interval_(0,-1) { 00083 set_type(0); 00084 audit(); 00085 compute_approximation(); 00086 } 00087 00088 00090 Simple_interval_root(const std::pair<NT,NT> &ii, 00091 const Polynomial &sa, 00092 Sign slb, Sign, 00093 Traits k): ii_(ii), function_(sa), 00094 kernel_(k), interval_(0,-1){ 00095 //CGAL_Polynomial_precondition(!ii_.is_singular()); 00096 //Sign slb= sign_(ii_.lower_bound()); 00097 if (slb == CGAL::NEGATIVE) { 00098 set_type(UP); 00099 } else { 00100 set_type(0); 00101 } 00102 compute_approximation(); 00103 audit(); 00104 } 00105 00106 static This infinity() { 00107 static This ret(std::numeric_limits<double>::infinity()); 00108 CGAL_Polynomial_postcondition(ret.is_infinite()); 00109 //ret.compute_approximation(); 00110 return ret; 00111 } 00112 00113 bool operator<(const This &o) const 00114 { 00115 CGAL_Polynomial_expensive_precondition(!is_null() && !o.is_null()); 00116 Comparison_result r= compare(o); 00117 audit(); o.audit(); 00118 return r==SMALLER; 00119 } 00120 00121 bool operator>(const This &o) const 00122 { 00123 CGAL_Polynomial_expensive_precondition(!is_null() && !o.is_null()); 00124 Comparison_result r= compare(o); 00125 audit(); o.audit(); 00126 return r==LARGER; 00127 } 00128 00129 bool operator!=(const This &o) const 00130 { 00131 if (is_null()) return !o.is_null(); 00132 else if (o.is_null()) return true; 00133 CGAL_Polynomial_expensive_precondition(!is_null() && !o.is_null()); 00134 Comparison_result r= compare(o); 00135 audit(); o.audit(); 00136 return r != EQUAL; 00137 } 00138 bool operator<=(const This &o) const 00139 { 00140 CGAL_Polynomial_expensive_precondition(!is_null() && !o.is_null()); 00141 Comparison_result r= compare(o); 00142 audit(); o.audit(); 00143 return r != LARGER; 00144 } 00145 bool operator>=(const This &o) const 00146 { 00147 CGAL_Polynomial_expensive_precondition(!is_null() && !o.is_null()); 00148 Comparison_result r= compare(o); 00149 audit(); o.audit(); 00150 return r != SMALLER; 00151 } 00152 00153 bool operator==(const This &o) const 00154 { 00155 if (is_null()) return o.is_null(); 00156 else if (o.is_null()) return false; 00157 CGAL_Polynomial_expensive_precondition(!is_null() && !o.is_null()); 00158 Comparison_result r= compare(o); 00159 audit(); o.audit(); 00160 return r==EQUAL; 00161 } 00162 00163 00164 const std::pair<NT, NT>& isolating_interval() const 00165 { 00166 CGAL_Polynomial_precondition(!is_infinite()); 00167 CGAL_Polynomial_expensive_precondition(!is_null()); 00168 return ii_; 00169 } 00170 00172 void write(std::ostream &o) const 00173 { 00174 #ifndef NDEBUG 00175 This t=*this; 00176 t.write_internal(o); 00177 #else 00178 write_internal(o); 00179 #endif 00180 } 00181 00182 void print() const 00183 { 00184 write(std::cout); 00185 } 00186 00188 This operator-() const 00189 { 00190 CGAL_Polynomial_expensive_precondition(!is_null()); 00191 if (is_pos_inf()) { 00192 This ret; 00193 ret.type_=INF; 00194 return ret; 00195 } else if (is_neg_inf()) return infinity(); 00196 else { 00197 This copy= *this; 00198 copy.ii_= std::make_pair(-ii_.second, -ii_.first); 00199 typename Traits::Negate_variable nf= kernel_.negate_variable_object(); 00200 copy.function_= nf(function_); 00201 if (type_&UP) { 00202 copy.type_= 0; 00203 } else { 00204 copy.type_=UP; 00205 } 00206 return copy; 00207 } 00208 } 00209 00211 bool is_infinite() const 00212 { 00213 return type_&INF; 00214 } 00215 00216 00217 Comparison_result compare(const This &o) const 00218 { 00219 audit(); 00220 o.audit(); 00221 CGAL_Polynomial_precondition(-SMALLER == LARGER); 00222 if (is_infinite() || o.is_infinite()) { 00223 if (is_pos_inf() && o.is_pos_inf()) return EQUAL; 00224 if (is_neg_inf() && o.is_neg_inf()) return EQUAL; 00225 else if (is_pos_inf() || o.is_neg_inf()) return LARGER; 00226 else if (is_neg_inf() || o.is_pos_inf()) return SMALLER; 00227 else { 00228 CGAL_Polynomial_assertion(0); return EQUAL; 00229 } 00230 } else { 00231 CGAL::Comparison_result cmp; 00232 if (try_compare(o, cmp)) return cmp; 00233 else return compare_finite(o); 00234 } 00235 } 00236 std::pair<double, double> compute_interval(double accuracy=.0001) const 00237 { 00238 if (interval_.first > interval_.second) { 00239 //std::cout << "Computing interval for "; 00240 //write_raw(std::cout) << std::endl; 00241 std::pair<double,double> r= internal_compute_interval(accuracy); 00242 /*std::cout << "Got " << CGAL::to_interval(ii_.first).first << "..." 00243 << CGAL::to_interval(ii_.second).second << std::endl;*/ 00244 interval_=std::make_pair(CGAL::to_interval(ii_.first).first, CGAL::to_interval(ii_.second).second); 00245 } 00246 return interval_; 00247 } 00248 00249 double compute_double(double accuracy) const 00250 { 00251 if (is_infinite()) { 00252 if (is_up()) { 00253 return double_inf_rep(); 00254 } 00255 else { 00256 return -double_inf_rep(); 00257 } 00258 } 00259 //This t= *this; 00260 std::pair<double, double> i= compute_interval(accuracy); 00261 return (i.first+i.second)/2.0; 00262 } 00263 00264 00265 NT rational_between(const This &o) const { 00266 CGAL_precondition(CGAL::compare(*this,o) == CGAL::SMALLER); 00267 CGAL_precondition(ii_.first != ii_.second || ii_.second != o.ii_.first || o.ii_.first != o.ii_.second); 00268 compare(o); 00269 CGAL_precondition(ii_.first != ii_.second || ii_.second != o.ii_.first || o.ii_.first != o.ii_.second); 00270 //write_internal(std::cout) << std::endl; 00271 //write_internal(std::cout) << std::endl; 00272 if (is_neg_inf()) return o.ii_.first -1; 00273 00274 // hopefully disjoint 00275 NT ret = ii_.second; 00276 NT step= NT(.0000000596046447753906250000000); 00277 00278 do { 00279 while (This(ret) <= *this) { 00280 ret+= step; 00281 } 00282 while (This(ret) >= o) { 00283 ret -= step; 00284 } 00285 step= step/NT(2.0); 00286 /*std::cout << ret << " (" << step << ")" 00287 << o.ii_.first - ii_.second 00288 << " " << o.ii_.second- ii_.first << std::endl;*/ 00289 } while (This(ret) >= o || This(ret) <= *this); 00290 return ret; 00291 } 00292 00293 protected: 00294 std::pair<double, double> internal_compute_interval(double accuracy) const 00295 { 00296 00297 if (type_&INF) { 00298 if (is_up()) { 00299 return std::pair<double, double>(double_inf_rep(), double_inf_rep()); 00300 } 00301 else { 00302 return std::pair<double, double>(-double_inf_rep(), -double_inf_rep()); 00303 } 00304 } 00305 00306 //double oaw; //= ii_.approximate_width(); 00307 // int ct=0; 00308 while (ii_.second != ii_.first && ii_.second-ii_.first > NT(accuracy)) { 00309 refine(); 00310 /*++ct; 00311 if (ct== 30) { 00312 std::cerr << "Error subdividing "; 00313 write_internal(std::cerr) << std::endl; 00314 break; 00315 }*/ 00316 } 00317 return std::make_pair(CGAL::to_interval(ii_.first).first, CGAL::to_interval(ii_.second).second); 00318 } 00319 std::ostream& write_internal(std::ostream &o) const 00320 { 00321 if (is_pos_inf()) { 00322 o << "inf"; 00323 } 00324 else if (is_neg_inf()) { 00325 o << "-inf"; 00326 } 00327 else { 00328 if (ii_.first == ii_.second) { 00329 o << ii_.first; 00330 } else { 00331 o << function_ << " in [" << ii_.first << "," << ii_.second << "]"; 00332 o << " = " << internal_compute_interval(.00001).first 00333 << "..." << internal_compute_interval(.00001).second; 00334 } 00335 } 00336 return o; 00337 } 00338 00339 std::ostream & write_raw(std::ostream &o) const 00340 { 00341 if (is_pos_inf()) { 00342 o << "inf"; 00343 } 00344 else if (is_neg_inf()) { 00345 o << "-inf"; 00346 } 00347 else { 00348 if (ii_.first == ii_.second) { 00349 o << ii_.first; 00350 } else { 00351 o << function_ << " in [" << ii_.first << "," << ii_.second << "]"; 00352 } 00353 } 00354 return o; 00355 } 00356 00357 void set_type(Type t) 00358 { 00359 type_=t; 00360 } 00361 00362 bool is_pos_inf() const 00363 { 00364 return (type_&INF) && (type_&UP); 00365 } 00366 00367 bool is_neg_inf() const 00368 { 00369 return (type_&INF) && !(type_&UP); 00370 } 00371 00372 bool contains_root(Sign ls, Sign us) const 00373 { 00374 return (is_up() && ls==NEGATIVE && us==POSITIVE) || (is_down() && ls==POSITIVE && us==NEGATIVE); 00375 } 00376 00377 void refine() const 00378 { 00379 if (ii_.first == ii_.second) return; 00380 //CGAL_Polynomial_precondition(!is_rational()); 00381 //CGAL_Polynomial_precondition(is_normal()); 00382 NT mp = (ii_.first + ii_.second)*NT(0.5); 00383 Sign sn= sign_at(mp); 00384 if (sn == ZERO) { 00385 ii_= std::make_pair(mp,mp); 00386 } else if (contains_root(lower_sign(), sn)) { 00387 ii_.second= mp; 00388 } else { 00389 ii_.first= mp; 00390 } 00391 } 00392 00393 void refine_using(const std::pair<NT, NT> &o) const 00394 { 00395 if (ii_.first== ii_.second) return; 00396 std::vector<NT > plist; 00397 plist.push_back(ii_.first); 00398 if (o.first < ii_.second && o.first > ii_.first) { 00399 plist.push_back(o.first); 00400 } 00401 if (o.first != o.second && o.second < ii_.second && o.second > ii_.first) { 00402 plist.push_back(o.second); 00403 } 00404 plist.push_back(ii_.second); 00405 00406 /*for (unsigned int i=0; i< plist.size(); ++i) { 00407 std::cout << plist[i] << " "; 00408 } 00409 std::cout << std::endl;*/ 00410 00411 if (plist.size()==2) return; 00412 00413 CGAL::Sign ps= lower_sign(); 00414 //std::cout << "ps is " << ps << std::endl; 00415 CGAL_assertion(ps != CGAL::ZERO); 00416 for (unsigned int i=1; i< plist.size()-1; ++i) { 00417 CGAL::Sign sn= sign_at(plist[i]); 00418 //std::cout << "sn is " << ps << std::endl; 00419 if (sn==0) { 00420 ii_= std::make_pair(plist[i], plist[i]); 00421 audit(); 00422 return; 00423 } else if (sn != ps) { 00424 ii_= std::make_pair(plist[i-1], plist[i]); 00425 audit(); 00426 return; 00427 } 00428 } 00429 00430 ii_= std::make_pair(plist[plist.size()-2], plist[plist.size()-1]); 00431 CGAL_postcondition(sign_at(plist[plist.size()-2]) == ps); 00432 CGAL_postcondition(sign_at(plist[plist.size()-1]) == -ps); 00433 audit(); 00434 } 00435 00436 Comparison_result compare_finite(const This &o) const 00437 { 00438 audit(); 00439 o.audit(); 00440 00441 refine_using(o.ii_); 00442 o.refine_using(ii_); 00443 00444 do { 00445 audit(); o.audit(); 00446 00447 CGAL::Comparison_result cmp; 00448 if (try_compare(o, cmp)) return cmp; 00449 00450 refine(); 00451 o.refine(); 00452 } while (ii_.second-ii_.first > NT(.0000001)); 00453 00454 //std::cout << "Using sturm to compare " << *this << " and " << o << std::endl; 00455 00456 typename Traits::Compare_isolated_roots_in_interval pred=kernel_.compare_isolated_roots_in_interval_object(function_,o.function_); 00457 Comparison_result co= pred(ii_.first, ii_.second); 00458 //std::cout << "The result is " << co << std::endl; 00459 return co; 00460 } 00461 00463 void audit() const 00464 { 00465 CGAL_Polynomial_assertion(!is_null()); 00466 #ifndef NDEBUG 00467 bool problem=false; 00468 if (type_&INF) { 00469 00470 } else if (ii_.first == ii_.second) { 00471 00472 } else { 00473 if (is_up()) { 00474 problem = problem || (sign_at(ii_.first) != NEGATIVE); 00475 problem = problem || (sign_at(ii_.second) != POSITIVE); 00476 } else { 00477 problem = problem || (sign_at(ii_.first) != POSITIVE); 00478 problem = problem || (sign_at(ii_.second) != NEGATIVE); 00479 } 00480 } 00481 if (problem) { 00482 std::cerr << "Problem with interval.\n"; 00483 std::cerr << "Type is " << type_ << std::endl; 00484 std::cerr << ii_.first << "..." << ii_.second << ", " << sign_at(ii_.first) 00485 << sign_at(ii_.second) << std::endl; 00486 CGAL_Polynomial_exactness_assertion(0); 00487 } 00488 #endif 00489 } 00490 00491 00492 00493 CGAL::Sign sign_at(const NT &nt) const 00494 { 00495 return kernel_.sign_at_object()(function_, nt); 00496 } 00497 00499 /*static This negative_infinity(){ 00500 This ret(INF); 00501 //ret.set_type(INF); 00502 //ret.compute_approximation(); 00503 return ret; 00504 }*/ 00505 00506 bool try_compare(const This &o, CGAL::Comparison_result &cmp) const { 00507 if (ii_.first == ii_.second){ 00508 if (o.ii_.first == o.ii_.second) { 00509 cmp= CGAL::compare(ii_.first, o.ii_.second); 00510 return true; 00511 } else { 00512 if (o.ii_.first < ii_.first && o.ii_.second > ii_.first) { 00513 return false; 00514 } else { 00515 cmp= CGAL::compare(ii_.first, o.ii_.first); 00516 if (cmp == CGAL::EQUAL){ 00517 cmp= CGAL::compare(ii_.first, o.ii_.second); 00518 } 00519 //CGAL_assertion(CGAL::compare(ii_.second, o.ii_.second) == cmp); 00520 return true; 00521 } 00522 } 00523 } else if (o.ii_.first == o.ii_.second) { 00524 if (ii_.first < o.ii_.first && ii_.second > o.ii_.first) { 00525 return false; 00526 } else { 00527 cmp= CGAL::compare(ii_.first, o.ii_.first); 00528 if (cmp == CGAL::EQUAL) { 00529 cmp= CGAL::compare(ii_.second, o.ii_.first); 00530 } 00531 //CGAL_assertion(CGAL::compare(ii_.second, o.ii_.second) == cmp); 00532 return true; 00533 } 00534 } else { 00535 if (ii_.first >= o.ii_.second) { 00536 cmp= CGAL::LARGER; 00537 return true; 00538 } else if (ii_.second <= o.ii_.first) { 00539 cmp= CGAL::SMALLER; 00540 return true; 00541 } else return false; 00542 } 00543 } 00544 00545 bool is_up() const 00546 { 00547 return type_&UP; 00548 } 00549 bool is_down() const 00550 { 00551 return !(type_&UP); 00552 } 00553 00554 static double double_inf_rep() { 00555 if (std::numeric_limits<double>::has_infinity) { 00556 return (std::numeric_limits<double>::infinity()); 00557 } else return ((std::numeric_limits<double>::max)()); 00558 } 00559 00560 Sign lower_sign() const 00561 { 00562 CGAL_Polynomial_precondition(!is_infinite()); 00563 if (is_up()) return NEGATIVE; 00564 else return POSITIVE; 00565 } 00566 00568 void compute_approximation() { 00569 #ifndef NDEBUG 00570 approximation_=immutable_double_approximation(0.0001); 00571 #endif 00572 } 00573 00574 double immutable_double_approximation(double accuracy=0.00001) const 00575 { 00576 CGAL_Polynomial_expensive_precondition(!is_null()); 00577 This temp = *this; 00578 return temp.internal_compute_interval(accuracy).first; 00579 } 00580 00582 bool is_null() const 00583 { 00584 return (type_&INVALID); 00585 } 00586 00587 mutable std::pair<NT, NT> ii_; 00588 //Function f_; 00589 Type type_; 00590 Polynomial function_; 00591 Traits kernel_; 00592 mutable std::pair<double,double> interval_; 00593 #ifndef NDEBUG 00594 double approximation_; 00595 #endif 00596 }; 00597 00598 /* 00599 template <class F> 00600 double to_double(const Simple_interval_root<F> &f){ 00601 return f.to_double(); 00602 } 00603 00604 template <class F> 00605 std::pair<double,double> to_interval(const Simple_interval_root<F> &f){ 00606 return f.to_ii_; 00607 }*/ 00608 00609 template <class F> 00610 std::ostream &operator<<(std::ostream &out, const Simple_interval_root<F> &f) 00611 { 00612 f.write(out); 00613 return out; 00614 } 00615 00616 /* 00617 template <class F> 00618 bool root_is_even_multiplicity(const Simple_interval_root<F> &f) 00619 { 00620 return f.is_even_multiplicity(); 00621 } 00622 00623 00624 template <class F> 00625 typename F::NT to_rational(const Simple_interval_root<F> &f) 00626 { 00627 return f.to_rational(); 00628 } 00629 00630 00631 template <class F> 00632 bool is_rational(const Simple_interval_root<F> &f) 00633 { 00634 return f.is_rational(); 00635 }*/ 00636 00637 00638 CGAL_POLYNOMIAL_END_INTERNAL_NAMESPACE 00639 00640 CGAL_BEGIN_NAMESPACE 00641 00642 00643 template <class T> 00644 class Real_embeddable_traits< CGAL::POLYNOMIAL::internal::Simple_interval_root<T> > 00645 : public INTERN_RET::Real_embeddable_traits_base< CGAL::POLYNOMIAL::internal::Simple_interval_root<T> , Tag_true > { 00646 public: 00647 typedef CGAL::POLYNOMIAL::internal::Simple_interval_root<T> Type; 00648 class Abs 00649 : public std::unary_function< Type, Type > { 00650 public: 00651 Type operator()( const Type& x ) const { 00652 if (x < Type(0)) return -x; 00653 else return x; 00654 } 00655 }; 00656 00657 class Sgn 00658 : public std::unary_function< Type, ::CGAL::Sign > { 00659 public: 00660 ::CGAL::Sign operator()( const Type& x ) const { 00661 return static_cast<CGAL::Sign>(x.compare(0)); 00662 } 00663 }; 00664 00665 class Compare 00666 : public std::binary_function< Type, Type, 00667 Comparison_result > { 00668 public: 00669 Comparison_result operator()( const Type& x, 00670 const Type& y ) const { 00671 return x.compare(y); 00672 } 00673 00674 CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR_WITH_RT( Type, 00675 Comparison_result ) 00676 00677 }; 00678 00679 class To_double 00680 : public std::unary_function< Type, double > { 00681 public: 00682 double operator()( const Type& x ) const { 00683 // this call is required to get reasonable values for the double 00684 // approximation 00685 return x.compute_double(.00000001); 00686 } 00687 }; 00688 00689 class To_interval 00690 : public std::unary_function< Type, std::pair< double, double > > { 00691 public: 00692 std::pair<double, double> operator()( const Type& x ) const { 00693 00694 return x.compute_interval(.00001); 00695 } 00696 }; 00697 }; 00698 00699 00700 00701 CGAL_END_NAMESPACE 00702 00703 namespace std 00704 { 00705 template <class Tr> 00706 class numeric_limits<CGAL_POLYNOMIAL_NS::internal::Simple_interval_root<Tr> > 00707 { 00708 public: 00709 typedef CGAL_POLYNOMIAL_NS::internal::Simple_interval_root<Tr> T; 00710 static const bool is_specialized = true; 00711 static T min BOOST_PREVENT_MACRO_SUBSTITUTION () throw () {return -T::infinity();} 00712 static T max BOOST_PREVENT_MACRO_SUBSTITUTION () throw () {return T::infinity();} 00713 static const int digits =0; 00714 static const int digits10 =0; 00715 static const bool is_signed = true; 00716 static const bool is_integer = false; 00717 static const bool is_exact = true; 00718 static const int radix =0; 00719 static T epsilon() throw(){return T(0);} 00720 static T round_error() throw(){return T(0);} 00721 static const int min_exponent=0; 00722 static const int min_exponent10=0; 00723 static const int max_exponent=0; 00724 static const int max_exponent10=0; 00725 static const bool has_infinity=true; 00726 static const bool has_quiet_NaN = true; 00727 static const bool has_signaling_NaN= false; 00728 static const float_denorm_style has_denorm= denorm_absent; 00729 static const bool has_denorm_loss = false; 00730 static T infinity() throw() {return T::infinity();} 00731 static T quiet_NaN() throw(){return T();} 00732 static T denorm_min() throw() {return T(0);} 00733 static const bool is_iec559=false; 00734 static const bool is_bounded =false; 00735 static const bool is_modulo= false; 00736 static const bool traps = false; 00737 static const bool tinyness_before =false; 00738 static const float_round_style round_stype = round_toward_zero; 00739 }; 00740 }; 00741 #endif