New URL for NEMO forge!   http://forge.nemo-ocean.eu

Since March 2022 along with NEMO 4.2 release, the code development moved to a self-hosted GitLab.
This present forge is now archived and remained online for history.
int_adapter.hpp in vendors/XIOS/current/extern/boost/include/boost/date_time – NEMO

source: vendors/XIOS/current/extern/boost/include/boost/date_time/int_adapter.hpp @ 3428

Last change on this file since 3428 was 3428, checked in by rblod, 12 years ago

importing initial XIOS vendor drop

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