wrapping_int.hpp 5.4 KB

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