annotate DEPENDENCIES/generic/include/boost/date_time/int_adapter.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 #ifndef _DATE_TIME_INT_ADAPTER_HPP__
Chris@16 2 #define _DATE_TIME_INT_ADAPTER_HPP__
Chris@16 3
Chris@16 4 /* Copyright (c) 2002,2003 CrystalClear Software, Inc.
Chris@16 5 * Use, modification and distribution is subject to the
Chris@16 6 * Boost Software License, Version 1.0. (See accompanying
Chris@16 7 * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
Chris@16 8 * Author: Jeff Garland, Bart Garst
Chris@101 9 * $Date$
Chris@16 10 */
Chris@16 11
Chris@16 12
Chris@16 13 #include "boost/config.hpp"
Chris@16 14 #include "boost/limits.hpp" //work around compilers without limits
Chris@16 15 #include "boost/date_time/special_defs.hpp"
Chris@16 16 #include "boost/date_time/locale_config.hpp"
Chris@16 17 #ifndef BOOST_DATE_TIME_NO_LOCALE
Chris@16 18 # include <ostream>
Chris@16 19 #endif
Chris@16 20
Chris@16 21 namespace boost {
Chris@16 22 namespace date_time {
Chris@16 23
Chris@16 24
Chris@16 25 //! Adapter to create integer types with +-infinity, and not a value
Chris@16 26 /*! This class is used internally in counted date/time representations.
Chris@16 27 * It adds the floating point like features of infinities and
Chris@16 28 * not a number. It also provides mathmatical operations with
Chris@16 29 * consideration to special values following these rules:
Chris@16 30 *@code
Chris@16 31 * +infinity - infinity == Not A Number (NAN)
Chris@16 32 * infinity * non-zero == infinity
Chris@16 33 * infinity * zero == NAN
Chris@16 34 * +infinity * -integer == -infinity
Chris@16 35 * infinity / infinity == NAN
Chris@16 36 * infinity * infinity == infinity
Chris@16 37 *@endcode
Chris@16 38 */
Chris@16 39 template<typename int_type_>
Chris@16 40 class int_adapter {
Chris@16 41 public:
Chris@16 42 typedef int_type_ int_type;
Chris@16 43 int_adapter(int_type v) :
Chris@16 44 value_(v)
Chris@16 45 {}
Chris@16 46 static bool has_infinity()
Chris@16 47 {
Chris@16 48 return true;
Chris@16 49 }
Chris@16 50 static const int_adapter pos_infinity()
Chris@16 51 {
Chris@16 52 return (::std::numeric_limits<int_type>::max)();
Chris@16 53 }
Chris@16 54 static const int_adapter neg_infinity()
Chris@16 55 {
Chris@16 56 return (::std::numeric_limits<int_type>::min)();
Chris@16 57 }
Chris@16 58 static const int_adapter not_a_number()
Chris@16 59 {
Chris@16 60 return (::std::numeric_limits<int_type>::max)()-1;
Chris@16 61 }
Chris@16 62 static int_adapter max BOOST_PREVENT_MACRO_SUBSTITUTION ()
Chris@16 63 {
Chris@16 64 return (::std::numeric_limits<int_type>::max)()-2;
Chris@16 65 }
Chris@16 66 static int_adapter min BOOST_PREVENT_MACRO_SUBSTITUTION ()
Chris@16 67 {
Chris@16 68 return (::std::numeric_limits<int_type>::min)()+1;
Chris@16 69 }
Chris@16 70 static int_adapter from_special(special_values sv)
Chris@16 71 {
Chris@16 72 switch (sv) {
Chris@16 73 case not_a_date_time: return not_a_number();
Chris@16 74 case neg_infin: return neg_infinity();
Chris@16 75 case pos_infin: return pos_infinity();
Chris@16 76 case max_date_time: return (max)();
Chris@16 77 case min_date_time: return (min)();
Chris@16 78 default: return not_a_number();
Chris@16 79 }
Chris@16 80 }
Chris@16 81 static bool is_inf(int_type v)
Chris@16 82 {
Chris@16 83 return (v == neg_infinity().as_number() ||
Chris@16 84 v == pos_infinity().as_number());
Chris@16 85 }
Chris@16 86 static bool is_neg_inf(int_type v)
Chris@16 87 {
Chris@16 88 return (v == neg_infinity().as_number());
Chris@16 89 }
Chris@16 90 static bool is_pos_inf(int_type v)
Chris@16 91 {
Chris@16 92 return (v == pos_infinity().as_number());
Chris@16 93 }
Chris@16 94 static bool is_not_a_number(int_type v)
Chris@16 95 {
Chris@16 96 return (v == not_a_number().as_number());
Chris@16 97 }
Chris@16 98 //! Returns either special value type or is_not_special
Chris@16 99 static special_values to_special(int_type v)
Chris@16 100 {
Chris@16 101 if (is_not_a_number(v)) return not_a_date_time;
Chris@16 102 if (is_neg_inf(v)) return neg_infin;
Chris@16 103 if (is_pos_inf(v)) return pos_infin;
Chris@16 104 return not_special;
Chris@16 105 }
Chris@16 106
Chris@16 107 //-3 leaves room for representations of infinity and not a date
Chris@16 108 static int_type maxcount()
Chris@16 109 {
Chris@16 110 return (::std::numeric_limits<int_type>::max)()-3;
Chris@16 111 }
Chris@16 112 bool is_infinity() const
Chris@16 113 {
Chris@16 114 return (value_ == neg_infinity().as_number() ||
Chris@16 115 value_ == pos_infinity().as_number());
Chris@16 116 }
Chris@16 117 bool is_pos_infinity()const
Chris@16 118 {
Chris@16 119 return(value_ == pos_infinity().as_number());
Chris@16 120 }
Chris@16 121 bool is_neg_infinity()const
Chris@16 122 {
Chris@16 123 return(value_ == neg_infinity().as_number());
Chris@16 124 }
Chris@16 125 bool is_nan() const
Chris@16 126 {
Chris@16 127 return (value_ == not_a_number().as_number());
Chris@16 128 }
Chris@16 129 bool is_special() const
Chris@16 130 {
Chris@16 131 return(is_infinity() || is_nan());
Chris@16 132 }
Chris@16 133 bool operator==(const int_adapter& rhs) const
Chris@16 134 {
Chris@16 135 return (compare(rhs) == 0);
Chris@16 136 }
Chris@16 137 bool operator==(const int& rhs) const
Chris@16 138 {
Chris@16 139 // quiets compiler warnings
Chris@16 140 bool is_signed = std::numeric_limits<int_type>::is_signed;
Chris@16 141 if(!is_signed)
Chris@16 142 {
Chris@16 143 if(is_neg_inf(value_) && rhs == 0)
Chris@16 144 {
Chris@16 145 return false;
Chris@16 146 }
Chris@16 147 }
Chris@16 148 return (compare(rhs) == 0);
Chris@16 149 }
Chris@16 150 bool operator!=(const int_adapter& rhs) const
Chris@16 151 {
Chris@16 152 return (compare(rhs) != 0);
Chris@16 153 }
Chris@16 154 bool operator!=(const int& rhs) const
Chris@16 155 {
Chris@16 156 // quiets compiler warnings
Chris@16 157 bool is_signed = std::numeric_limits<int_type>::is_signed;
Chris@16 158 if(!is_signed)
Chris@16 159 {
Chris@16 160 if(is_neg_inf(value_) && rhs == 0)
Chris@16 161 {
Chris@16 162 return true;
Chris@16 163 }
Chris@16 164 }
Chris@16 165 return (compare(rhs) != 0);
Chris@16 166 }
Chris@16 167 bool operator<(const int_adapter& rhs) const
Chris@16 168 {
Chris@16 169 return (compare(rhs) == -1);
Chris@16 170 }
Chris@16 171 bool operator<(const int& rhs) const
Chris@16 172 {
Chris@16 173 // quiets compiler warnings
Chris@16 174 bool is_signed = std::numeric_limits<int_type>::is_signed;
Chris@16 175 if(!is_signed)
Chris@16 176 {
Chris@16 177 if(is_neg_inf(value_) && rhs == 0)
Chris@16 178 {
Chris@16 179 return true;
Chris@16 180 }
Chris@16 181 }
Chris@16 182 return (compare(rhs) == -1);
Chris@16 183 }
Chris@16 184 bool operator>(const int_adapter& rhs) const
Chris@16 185 {
Chris@16 186 return (compare(rhs) == 1);
Chris@16 187 }
Chris@16 188 int_type as_number() const
Chris@16 189 {
Chris@16 190 return value_;
Chris@16 191 }
Chris@16 192 //! Returns either special value type or is_not_special
Chris@16 193 special_values as_special() const
Chris@16 194 {
Chris@16 195 return int_adapter::to_special(value_);
Chris@16 196 }
Chris@16 197 //creates nasty ambiguities
Chris@16 198 // operator int_type() const
Chris@16 199 // {
Chris@16 200 // return value_;
Chris@16 201 // }
Chris@16 202
Chris@16 203 /*! Operator allows for adding dissimilar int_adapter types.
Chris@16 204 * The return type will match that of the the calling object's type */
Chris@16 205 template<class rhs_type>
Chris@16 206 inline
Chris@16 207 int_adapter operator+(const int_adapter<rhs_type>& rhs) const
Chris@16 208 {
Chris@16 209 if(is_special() || rhs.is_special())
Chris@16 210 {
Chris@16 211 if (is_nan() || rhs.is_nan())
Chris@16 212 {
Chris@16 213 return int_adapter::not_a_number();
Chris@16 214 }
Chris@16 215 if((is_pos_inf(value_) && rhs.is_neg_inf(rhs.as_number())) ||
Chris@16 216 (is_neg_inf(value_) && rhs.is_pos_inf(rhs.as_number())) )
Chris@16 217 {
Chris@16 218 return int_adapter::not_a_number();
Chris@16 219 }
Chris@16 220 if (is_infinity())
Chris@16 221 {
Chris@16 222 return *this;
Chris@16 223 }
Chris@16 224 if (rhs.is_pos_inf(rhs.as_number()))
Chris@16 225 {
Chris@16 226 return int_adapter::pos_infinity();
Chris@16 227 }
Chris@16 228 if (rhs.is_neg_inf(rhs.as_number()))
Chris@16 229 {
Chris@16 230 return int_adapter::neg_infinity();
Chris@16 231 }
Chris@16 232 }
Chris@16 233 return int_adapter<int_type>(value_ + rhs.as_number());
Chris@16 234 }
Chris@16 235
Chris@16 236 int_adapter operator+(const int_type rhs) const
Chris@16 237 {
Chris@16 238 if(is_special())
Chris@16 239 {
Chris@16 240 if (is_nan())
Chris@16 241 {
Chris@16 242 return int_adapter<int_type>(not_a_number());
Chris@16 243 }
Chris@16 244 if (is_infinity())
Chris@16 245 {
Chris@16 246 return *this;
Chris@16 247 }
Chris@16 248 }
Chris@16 249 return int_adapter<int_type>(value_ + rhs);
Chris@16 250 }
Chris@16 251
Chris@16 252 /*! Operator allows for subtracting dissimilar int_adapter types.
Chris@16 253 * The return type will match that of the the calling object's type */
Chris@16 254 template<class rhs_type>
Chris@16 255 inline
Chris@16 256 int_adapter operator-(const int_adapter<rhs_type>& rhs)const
Chris@16 257 {
Chris@16 258 if(is_special() || rhs.is_special())
Chris@16 259 {
Chris@16 260 if (is_nan() || rhs.is_nan())
Chris@16 261 {
Chris@16 262 return int_adapter::not_a_number();
Chris@16 263 }
Chris@16 264 if((is_pos_inf(value_) && rhs.is_pos_inf(rhs.as_number())) ||
Chris@16 265 (is_neg_inf(value_) && rhs.is_neg_inf(rhs.as_number())) )
Chris@16 266 {
Chris@16 267 return int_adapter::not_a_number();
Chris@16 268 }
Chris@16 269 if (is_infinity())
Chris@16 270 {
Chris@16 271 return *this;
Chris@16 272 }
Chris@16 273 if (rhs.is_pos_inf(rhs.as_number()))
Chris@16 274 {
Chris@16 275 return int_adapter::neg_infinity();
Chris@16 276 }
Chris@16 277 if (rhs.is_neg_inf(rhs.as_number()))
Chris@16 278 {
Chris@16 279 return int_adapter::pos_infinity();
Chris@16 280 }
Chris@16 281 }
Chris@16 282 return int_adapter<int_type>(value_ - rhs.as_number());
Chris@16 283 }
Chris@16 284 int_adapter operator-(const int_type rhs) const
Chris@16 285 {
Chris@16 286 if(is_special())
Chris@16 287 {
Chris@16 288 if (is_nan())
Chris@16 289 {
Chris@16 290 return int_adapter<int_type>(not_a_number());
Chris@16 291 }
Chris@16 292 if (is_infinity())
Chris@16 293 {
Chris@16 294 return *this;
Chris@16 295 }
Chris@16 296 }
Chris@16 297 return int_adapter<int_type>(value_ - rhs);
Chris@16 298 }
Chris@16 299
Chris@16 300 // should templatize this to be consistant with op +-
Chris@16 301 int_adapter operator*(const int_adapter& rhs)const
Chris@16 302 {
Chris@16 303 if(this->is_special() || rhs.is_special())
Chris@16 304 {
Chris@16 305 return mult_div_specials(rhs);
Chris@16 306 }
Chris@16 307 return int_adapter<int_type>(value_ * rhs.value_);
Chris@16 308 }
Chris@16 309 /*! Provided for cases when automatic conversion from
Chris@16 310 * 'int' to 'int_adapter' causes incorrect results. */
Chris@16 311 int_adapter operator*(const int rhs) const
Chris@16 312 {
Chris@16 313 if(is_special())
Chris@16 314 {
Chris@16 315 return mult_div_specials(rhs);
Chris@16 316 }
Chris@16 317 return int_adapter<int_type>(value_ * rhs);
Chris@16 318 }
Chris@16 319
Chris@16 320 // should templatize this to be consistant with op +-
Chris@16 321 int_adapter operator/(const int_adapter& rhs)const
Chris@16 322 {
Chris@16 323 if(this->is_special() || rhs.is_special())
Chris@16 324 {
Chris@16 325 if(is_infinity() && rhs.is_infinity())
Chris@16 326 {
Chris@16 327 return int_adapter<int_type>(not_a_number());
Chris@16 328 }
Chris@16 329 if(rhs != 0)
Chris@16 330 {
Chris@16 331 return mult_div_specials(rhs);
Chris@16 332 }
Chris@16 333 else { // let divide by zero blow itself up
Chris@16 334 return int_adapter<int_type>(value_ / rhs.value_);
Chris@16 335 }
Chris@16 336 }
Chris@16 337 return int_adapter<int_type>(value_ / rhs.value_);
Chris@16 338 }
Chris@16 339 /*! Provided for cases when automatic conversion from
Chris@16 340 * 'int' to 'int_adapter' causes incorrect results. */
Chris@16 341 int_adapter operator/(const int rhs) const
Chris@16 342 {
Chris@16 343 if(is_special() && rhs != 0)
Chris@16 344 {
Chris@16 345 return mult_div_specials(rhs);
Chris@16 346 }
Chris@16 347 return int_adapter<int_type>(value_ / rhs);
Chris@16 348 }
Chris@16 349
Chris@16 350 // should templatize this to be consistant with op +-
Chris@16 351 int_adapter operator%(const int_adapter& rhs)const
Chris@16 352 {
Chris@16 353 if(this->is_special() || rhs.is_special())
Chris@16 354 {
Chris@16 355 if(is_infinity() && rhs.is_infinity())
Chris@16 356 {
Chris@16 357 return int_adapter<int_type>(not_a_number());
Chris@16 358 }
Chris@16 359 if(rhs != 0)
Chris@16 360 {
Chris@16 361 return mult_div_specials(rhs);
Chris@16 362 }
Chris@16 363 else { // let divide by zero blow itself up
Chris@16 364 return int_adapter<int_type>(value_ % rhs.value_);
Chris@16 365 }
Chris@16 366 }
Chris@16 367 return int_adapter<int_type>(value_ % rhs.value_);
Chris@16 368 }
Chris@16 369 /*! Provided for cases when automatic conversion from
Chris@16 370 * 'int' to 'int_adapter' causes incorrect results. */
Chris@16 371 int_adapter operator%(const int rhs) const
Chris@16 372 {
Chris@16 373 if(is_special() && rhs != 0)
Chris@16 374 {
Chris@16 375 return mult_div_specials(rhs);
Chris@16 376 }
Chris@16 377 return int_adapter<int_type>(value_ % rhs);
Chris@16 378 }
Chris@16 379 private:
Chris@16 380 int_type value_;
Chris@16 381
Chris@16 382 //! returns -1, 0, 1, or 2 if 'this' is <, ==, >, or 'nan comparison' rhs
Chris@16 383 int compare(const int_adapter& rhs)const
Chris@16 384 {
Chris@16 385 if(this->is_special() || rhs.is_special())
Chris@16 386 {
Chris@16 387 if(this->is_nan() || rhs.is_nan()) {
Chris@16 388 if(this->is_nan() && rhs.is_nan()) {
Chris@16 389 return 0; // equal
Chris@16 390 }
Chris@16 391 else {
Chris@16 392 return 2; // nan
Chris@16 393 }
Chris@16 394 }
Chris@16 395 if((is_neg_inf(value_) && !is_neg_inf(rhs.value_)) ||
Chris@16 396 (is_pos_inf(rhs.value_) && !is_pos_inf(value_)) )
Chris@16 397 {
Chris@16 398 return -1; // less than
Chris@16 399 }
Chris@16 400 if((is_pos_inf(value_) && !is_pos_inf(rhs.value_)) ||
Chris@16 401 (is_neg_inf(rhs.value_) && !is_neg_inf(value_)) ) {
Chris@16 402 return 1; // greater than
Chris@16 403 }
Chris@16 404 }
Chris@16 405 if(value_ < rhs.value_) return -1;
Chris@16 406 if(value_ > rhs.value_) return 1;
Chris@16 407 // implied-> if(value_ == rhs.value_)
Chris@16 408 return 0;
Chris@16 409 }
Chris@16 410 /* When multiplying and dividing with at least 1 special value
Chris@16 411 * very simmilar rules apply. In those cases where the rules
Chris@16 412 * are different, they are handled in the respective operator
Chris@16 413 * function. */
Chris@16 414 //! Assumes at least 'this' or 'rhs' is a special value
Chris@16 415 int_adapter mult_div_specials(const int_adapter& rhs)const
Chris@16 416 {
Chris@16 417 int min_value;
Chris@16 418 // quiets compiler warnings
Chris@16 419 bool is_signed = std::numeric_limits<int_type>::is_signed;
Chris@16 420 if(is_signed) {
Chris@16 421 min_value = 0;
Chris@16 422 }
Chris@16 423 else {
Chris@16 424 min_value = 1;// there is no zero with unsigned
Chris@16 425 }
Chris@16 426 if(this->is_nan() || rhs.is_nan()) {
Chris@16 427 return int_adapter<int_type>(not_a_number());
Chris@16 428 }
Chris@16 429 if((*this > 0 && rhs > 0) || (*this < min_value && rhs < min_value)) {
Chris@16 430 return int_adapter<int_type>(pos_infinity());
Chris@16 431 }
Chris@16 432 if((*this > 0 && rhs < min_value) || (*this < min_value && rhs > 0)) {
Chris@16 433 return int_adapter<int_type>(neg_infinity());
Chris@16 434 }
Chris@16 435 //implied -> if(this->value_ == 0 || rhs.value_ == 0)
Chris@16 436 return int_adapter<int_type>(not_a_number());
Chris@16 437 }
Chris@16 438 /* Overloaded function necessary because of special
Chris@16 439 * situation where int_adapter is instantiated with
Chris@16 440 * 'unsigned' and func is called with negative int.
Chris@16 441 * It would produce incorrect results since 'unsigned'
Chris@16 442 * wraps around when initialized with a negative value */
Chris@16 443 //! Assumes 'this' is a special value
Chris@16 444 int_adapter mult_div_specials(const int& rhs) const
Chris@16 445 {
Chris@16 446 int min_value;
Chris@16 447 // quiets compiler warnings
Chris@16 448 bool is_signed = std::numeric_limits<int_type>::is_signed;
Chris@16 449 if(is_signed) {
Chris@16 450 min_value = 0;
Chris@16 451 }
Chris@16 452 else {
Chris@16 453 min_value = 1;// there is no zero with unsigned
Chris@16 454 }
Chris@16 455 if(this->is_nan()) {
Chris@16 456 return int_adapter<int_type>(not_a_number());
Chris@16 457 }
Chris@16 458 if((*this > 0 && rhs > 0) || (*this < min_value && rhs < 0)) {
Chris@16 459 return int_adapter<int_type>(pos_infinity());
Chris@16 460 }
Chris@16 461 if((*this > 0 && rhs < 0) || (*this < min_value && rhs > 0)) {
Chris@16 462 return int_adapter<int_type>(neg_infinity());
Chris@16 463 }
Chris@16 464 //implied -> if(this->value_ == 0 || rhs.value_ == 0)
Chris@16 465 return int_adapter<int_type>(not_a_number());
Chris@16 466 }
Chris@16 467
Chris@16 468 };
Chris@16 469
Chris@16 470 #ifndef BOOST_DATE_TIME_NO_LOCALE
Chris@16 471 /*! Expected output is either a numeric representation
Chris@16 472 * or a special values representation.<BR>
Chris@16 473 * Ex. "12", "+infinity", "not-a-number", etc. */
Chris@16 474 //template<class charT = char, class traits = std::traits<charT>, typename int_type>
Chris@16 475 template<class charT, class traits, typename int_type>
Chris@16 476 inline
Chris@16 477 std::basic_ostream<charT, traits>&
Chris@16 478 operator<<(std::basic_ostream<charT, traits>& os, const int_adapter<int_type>& ia)
Chris@16 479 {
Chris@16 480 if(ia.is_special()) {
Chris@16 481 // switch copied from date_names_put.hpp
Chris@16 482 switch(ia.as_special())
Chris@16 483 {
Chris@16 484 case not_a_date_time:
Chris@16 485 os << "not-a-number";
Chris@16 486 break;
Chris@16 487 case pos_infin:
Chris@16 488 os << "+infinity";
Chris@16 489 break;
Chris@16 490 case neg_infin:
Chris@16 491 os << "-infinity";
Chris@16 492 break;
Chris@16 493 default:
Chris@16 494 os << "";
Chris@16 495 }
Chris@16 496 }
Chris@16 497 else {
Chris@16 498 os << ia.as_number();
Chris@16 499 }
Chris@16 500 return os;
Chris@16 501 }
Chris@16 502 #endif
Chris@16 503
Chris@16 504
Chris@16 505 } } //namespace date_time
Chris@16 506
Chris@16 507
Chris@16 508
Chris@16 509 #endif