source: NonGTP/Boost/boost/date_time/wrapping_int.hpp @ 857

Revision 857, 5.5 KB checked in by igarcia, 19 years ago (diff)
RevLine 
[857]1#ifndef _DATE_TIME_WRAPPING_INT_HPP__
2#define _DATE_TIME_WRAPPING_INT_HPP__
3
4/* Copyright (c) 2002,2003,2005 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 or http://www.boost.org/LICENSE-1.0)
8 * Author: Jeff Garland, Bart Garst
9 * $Date: 2005/10/24 01:32:08 $
10 */
11
12
13namespace boost {
14namespace date_time {
15
16//! A wrapping integer used to support time durations (WARNING: only instantiate with a signed type)
17/*! In composite date and time types this type is used to
18 *  wrap at the day boundary.
19 *  Ex:
20 *  A wrapping_int<short, 10> will roll over after nine, and
21 *  roll under below zero. This gives a range of [0,9]
22 *
23 * NOTE: it is strongly recommended that wrapping_int2 be used
24 * instead of wrapping_int as wrapping_int is to be depricated
25 * at some point soon.
26 *
27 * Also Note that warnings will occur if instantiated with an
28 * unsigned type. Only a signed type should be used!
29 */
30template<typename int_type_, int_type_ wrap_val>
31class wrapping_int {
32public:
33  typedef int_type_ int_type;
34  //typedef overflow_type_ overflow_type;
35  static int_type wrap_value() {return wrap_val;}
36  //!Add, return true if wrapped
37  wrapping_int(int_type v) : value_(v) {};
38  //! Explicit converion method
39  int_type as_int()   const   {return value_;}
40  operator int_type() const   {return value_;}
41  //!Add, return number of wraps performed
42  /*! The sign of the returned value will indicate which direction the
43   * wraps went. Ex: add a negative number and wrapping under could occur,
44   * this would be indicated by a negative return value. If wrapping over
45   * took place, a positive value would be returned */
46  int_type add(int_type v)
47  {
48    int_type remainder = static_cast<int_type>(v % (wrap_val));
49    int_type overflow = static_cast<int_type>(v / (wrap_val));
50    value_ = static_cast<int_type>(value_ + remainder);
51    return calculate_wrap(overflow);
52  }
53  //! Subtract will return '+d' if wrapping under took place ('d' is the number of wraps)
54  /*! The sign of the returned value will indicate which direction the
55   * wraps went (positive indicates wrap under, negative indicates wrap over).
56   * Ex: subtract a negative number and wrapping over could
57   * occur, this would be indicated by a negative return value. If
58   * wrapping under took place, a positive value would be returned. */
59  int_type subtract(int_type v)
60  {
61    int_type remainder = static_cast<int_type>(v % (wrap_val));
62    int_type underflow = static_cast<int_type>(-(v / (wrap_val)));
63    value_ = static_cast<int_type>(value_ - remainder);
64    return calculate_wrap(underflow) * -1;
65  }
66private:
67  int_type value_;
68
69  int_type calculate_wrap(int_type wrap)
70  {
71    if ((value_) >= wrap_val)
72    {
73      wrap++;
74      value_ -= (wrap_val);
75    }
76    else if(value_ < 0)
77    {
78      wrap--;
79      value_ += (wrap_val);
80    }
81    return wrap;
82  }
83                 
84};
85
86
87//! A wrapping integer used to wrap around at the top (WARNING: only instantiate with a signed type)
88/*! Bad name, quick impl to fix a bug -- fix later!!
89 *  This allows the wrap to restart at a value other than 0.
90 */
91template<typename int_type_, int_type_ wrap_min, int_type_ wrap_max>
92class wrapping_int2 {
93public:
94  typedef int_type_ int_type;
95  static unsigned long wrap_value() {return wrap_max;}
96  static unsigned long min_value()  {return wrap_min;}
97  /*! If initializing value is out of range of [wrap_min, wrap_max],
98   * value will be initialized to closest of min or max */
99  wrapping_int2(int_type v) : value_(v) {
100    if(value_ < wrap_min)
101    {
102      value_ = wrap_min;
103    }
104    if(value_ > wrap_max)
105    {
106      value_ = wrap_max;
107    }
108  }
109  //! Explicit converion method
110  int_type as_int()   const   {return value_;}
111  operator int_type() const {return value_;}
112  //!Add, return number of wraps performed
113  /*! The sign of the returned value will indicate which direction the
114   * wraps went. Ex: add a negative number and wrapping under could occur,
115   * this would be indicated by a negative return value. If wrapping over
116   * took place, a positive value would be returned */
117  int_type add(int_type v)
118  {
119    int_type remainder = static_cast<int_type>(v % (wrap_max - wrap_min + 1));
120    int_type overflow = static_cast<int_type>(v / (wrap_max - wrap_min + 1));
121    value_ = static_cast<int_type>(value_ + remainder);
122    return calculate_wrap(overflow);
123  }
124  //! Subtract will return '-d' if wrapping under took place ('d' is the number of wraps)
125  /*! The sign of the returned value will indicate which direction the
126   * wraps went. Ex: subtract a negative number and wrapping over could
127   * occur, this would be indicated by a positive return value. If
128   * wrapping under took place, a negative value would be returned */
129  int_type subtract(int_type v)
130  {
131    int_type remainder = static_cast<int_type>(v % (wrap_max - wrap_min + 1));
132    int_type underflow = static_cast<int_type>(-(v / (wrap_max - wrap_min + 1)));
133    value_ = static_cast<int_type>(value_ - remainder);
134    return calculate_wrap(underflow);
135  }
136           
137private:
138  int_type value_;
139
140  int_type calculate_wrap(int_type wrap)
141  {
142    if ((value_) > wrap_max)
143    {
144      wrap++;
145      value_ -= (wrap_max - wrap_min + 1);
146    }
147    else if((value_) < wrap_min)
148    {
149      wrap--;
150      value_ += (wrap_max - wrap_min + 1);
151    }
152    return wrap;
153  }
154};
155
156
157
158} } //namespace date_time
159
160
161
162#endif
163
Note: See TracBrowser for help on using the repository browser.