1:   
   2:  namespace Luschny.Math.MathUtils
   3:  {
   4:      using System;
   5:   
   6:      /// <summary>
   7:      /// a PositiveRange is an intervall of integers,
   8:      /// given by a lower bound Min and an upper bound Max,
   9:      /// such that 0 &lt;= Min and Min &lt;= Max.
  10:      /// a PositiveRange is immutable.
  11:      /// </summary>
  12:      public class PositiveRange : ICloneable
  13:      {
  14:          /// <summary>
  15:          /// Initializes a new instance of the PositiveRange class,
  16:          /// i.e. a range of integers, such that 0 &lt;= low &lt;= high.
  17:          /// </summary>
  18:          /// <param name="low"> The lower bound (Min) of the range.</param>
  19:          /// <param name="high"> The upper bound (Max) of the range.</param>
  20:          /// throws IllegalArgumentException
  21:          public PositiveRange(int low, int high)
  22:          {
  23:              if (!((0 <= low) && (low <= high)))
  24:              {
  25:                  throw new ArgumentOutOfRangeException(
  26:                  String.Format("[{0},{1}]", low, high),
  27:                  "The order 0 <= low <= high is false.");
  28:              }
  29:              
  30:              this.Min = low;
  31:              this.Max = high;
  32:          }
  33:   
  34:          /// <summary>
  35:          /// Gets the lower bound (Min) of the interval.
  36:          /// </summary>
  37:          public int Min { get; private set; } // C#3.0 
  38:   
  39:          /// <summary>
  40:          /// Gets upper bound (Max) of the interval.
  41:          /// </summary>
  42:          public int Max { get; private set; } // C#3.0
  43:   
  44:          /// <summary>
  45:          /// Represents the range as a string, formatted as "[Min,Max]".
  46:          /// </summary>
  47:          /// <returns>a string representation of the range.</returns>
  48:          public override string ToString()
  49:          {
  50:              return String.Format("[{0},{1}]", this.Min, this.Max);
  51:          }
  52:   
  53:          /// <summary>
  54:          /// Checks if the given value lies within the range,
  55:          /// i.e.  Min &lt;= value and value &lt;= Max.
  56:          /// </summary>
  57:          /// <param name="value">The value to checked.</param>
  58:          /// <returns>True, if the range includes the value, 
  59:          /// false otherwise.</returns>
  60:          public bool Contains(int value)
  61:          {
  62:              return (Min <= value) && (value <= Max);
  63:          }
  64:   
  65:          /// <summary>
  66:          /// Checks if the given value lies within the range,
  67:          /// bo.exp.  Min &lt;= value and value &lt;= Max.
  68:          /// If the value ist not contained an 
  69:          /// ArgumentOutOfRangeException will be raised.
  70:          /// </summary> 
  71:          /// <param name="value">The value to checked.</param>
  72:          /// <returns>True, if the range includes the value, 
  73:          /// false otherwise.</returns>
  74:          /// <exception cref="ArgumentOutOfRangeException"></exception>
  75:          public bool ContainsOrFail(int value)
  76:          {
  77:              if (!((this.Min <= value) && (value <= this.Max)))
  78:              {
  79:                  throw new System.ArgumentOutOfRangeException(
  80:                     new System.Text.StringBuilder(64).Append(this.ToString()).
  81:                     Append(" does not contain ").Append(value).ToString());
  82:              }
  83:              
  84:              return true;
  85:          }
  86:   
  87:          /// <summary>
  88:          /// Checks if the given range is a subrange,
  89:          /// bo.exp.  this.Min &lt;= range.Min and range.Max &lt;= this.Max.
  90:          /// </summary>
  91:          /// <param name="range">The range to be checked.</param>
  92:          /// <returns>True, if the given range lies within the bounds 
  93:          /// of this range, false otherwise.</returns>
  94:          public bool Contains(PositiveRange range)
  95:          {
  96:              return (Min <= range.Min) && (range.Max <= Max);
  97:          }
  98:   
  99:          /// <summary>
 100:          /// Checks if the given range is a subrange,
 101:          /// bo.exp.  this.Min &lt;= range.Min and range.Max &lt;= this.Max.
 102:          /// If the range ist not contained an ArgumentOutOfRangeException
 103:          /// will be raised. </summary>
 104:          /// <param name="range">The range to be checked.</param>
 105:          /// <returns>True, if the given range lies within the bounds 
 106:          /// of this range, false otherwise.</returns>
 107:          public bool ContainsOrFail(PositiveRange range)
 108:          {
 109:              if (!((this.Min <= range.Min) && (range.Max <= this.Max)))
 110:              {
 111:                  throw new System.ArgumentOutOfRangeException(
 112:                     new System.Text.StringBuilder(64).Append(this.ToString()).
 113:                     Append(" does not contain ").Append(range.ToString()).ToString());
 114:              }
 115:              
 116:              return true;
 117:          }
 118:   
 119:          /// <summary>
 120:          /// The Size of the range.
 121:          /// </summary>
 122:          /// <returns>The size of the range.</returns>
 123:          public int Size()
 124:          {
 125:              return this.Max - this.Min + 1;
 126:          }
 127:   
 128:          /// <summary>
 129:          /// Overrides System.Object.Clone()
 130:          /// </summary>
 131:          /// <returns>a clone of this range.</returns>
 132:          public object Clone()
 133:          {
 134:              return new PositiveRange(this.Min, this.Max);
 135:          }
 136:   
 137:          /// <summary>
 138:          /// Compares this range to the specified object. The result
 139:          /// is true if and only if the argument is not null and is a
 140:          /// PositiveRange object that has the same values as this object.
 141:          /// </summary>
 142:          /// <param name="obj"> The object to compare with.</param>
 143:          /// <returns> True if the object has the same values as this object; 
 144:          /// false otherwise. </returns>
 145:          public override bool Equals(object obj)
 146:          {
 147:              if (null == (object)obj)
 148:              {
 149:                  return false;
 150:              }
 151:   
 152:              // If parameter cannot be cast to PositiveRange return false.
 153:              PositiveRange that = obj as PositiveRange;
 154:              if ((object)that == null)
 155:              {
 156:                  return false;
 157:              }
 158:              
 159:              return this.Equals(that);
 160:          }
 161:   
 162:          /// <summary>
 163:          /// Compares this range to the specified range. The result is true
 164:          /// if and only if the argument has the same values as this object.
 165:          /// </summary>
 166:          /// <param name="that"> a positive range to compare with.</param>
 167:          /// <returns> True if the given range has the same bounds as 
 168:          /// this object; false otherwise. </returns>
 169:          public bool Equals(PositiveRange that)
 170:          {
 171:              if (null == (object)that)
 172:              {
 173:                  return false;
 174:              }
 175:   
 176:              // Return true if the fields match:
 177:              return (this.Min == that.Min) && (this.Max == that.Max);
 178:          }
 179:   
 180:          // By default, the operator == tests for reference equality by 
 181:          // determining whether two references indicate the same object. 
 182:          // PositiveRange is immutable, so overloading operator == to compare
 183:          // value equality instead of reference equality is useful because, 
 184:          // as immutable objects, two ranges can be considered the same as
 185:          // long as they have the same values Min and Max. 
 186:   
 187:          /// <summary>
 188:          /// Compares this range to the specified range. The result is true
 189:          /// if and only if the arguments have the same value.
 190:          /// </summary>
 191:          /// <param name="a"> a positive range.</param>
 192:          /// <param name="b"> a positive range.</param>
 193:          /// <returns> True if the two ranges have the same bounds;
 194:          /// false otherwise. </returns>
 195:          public static bool operator ==(PositiveRange a, PositiveRange b)
 196:          {
 197:              // If both are null, or both are same instance, return true.
 198:              if (System.Object.ReferenceEquals(a, b))
 199:              {
 200:                  return true;
 201:              }
 202:   
 203:              // If one is null, but not both, return false.
 204:              if (((object)a == null) || ((object)b == null))
 205:              {
 206:                  return false;
 207:              }
 208:   
 209:              // Return true if the fields match: 
 210:              // return a.Equals(b);
 211:              return (a.Min == b.Min) && (a.Max == b.Max);
 212:          }
 213:   
 214:          /// <summary>
 215:          /// Compares this range to the specified range. The result is true
 216:          /// if and only if the arguments do not have the same value.
 217:          /// </summary>
 218:          /// <param name="a"> a positive range.</param>
 219:          /// <param name="b"> a positive range.</param>
 220:          /// <returns> False if the two ranges have the same bounds;
 221:          /// true otherwise. </returns>
 222:          public static bool operator !=(PositiveRange a, PositiveRange b)
 223:          {
 224:              return !(a == b);
 225:          }
 226:   
 227:          /// <summary>
 228:          /// Compares two ranges with respect to inclusion. The result is true
 229:          /// if and only if the right hand side contains the left hand side.
 230:          /// </summary>
 231:          /// <param name="a"> a positive range.</param>
 232:          /// <param name="b"> a positive range.</param>
 233:          /// <returns> True if b contains a.</returns>
 234:          public static bool operator <=(PositiveRange a, PositiveRange b)
 235:          {
 236:              // If both are null, or both are same instance, return true.
 237:              if (System.Object.ReferenceEquals(a, b))
 238:              {
 239:                  return true;
 240:              }
 241:   
 242:              // If one is null, but not both, return false.
 243:              if (((object)a == null) || ((object)b == null))
 244:              {
 245:                  return false;
 246:              }
 247:   
 248:              return b.Contains(a);
 249:          }
 250:   
 251:          /// <summary>
 252:          /// Compares two ranges with respect to inclusion. The result is true
 253:          /// if and only if the left hand side contains the right hand side.
 254:          /// </summary>
 255:          /// <param name="a"> a positive range.</param>
 256:          /// <param name="b"> a positive range.</param>
 257:          /// <returns> True if a contains b.</returns>
 258:          public static bool operator >=(PositiveRange a, PositiveRange b)
 259:          {
 260:              // If both are null, or both are same instance, return true.
 261:              if (System.Object.ReferenceEquals(a, b))
 262:              {
 263:                  return true;
 264:              }
 265:   
 266:              // If one is null, but not both, return false.
 267:              if (((object)a == null) || ((object)b == null))
 268:              {
 269:                  return false;
 270:              }
 271:   
 272:              return a.Contains(b);
 273:          }
 274:   
 275:          /// <summary>
 276:          ///  a hash code value for this range.
 277:          /// </summary>  
 278:          /// <returns>Returns a hash code for this.</returns>
 279:          public override int GetHashCode()
 280:          {
 281:              return 29 * this.Min + this.Max;
 282:          }
 283:      }
 284:  }