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 <= Min and Min <= 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 <= low <= 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 <= value and value <= 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 <= value and value <= 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 <= range.Min and range.Max <= 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 <= range.Min and range.Max <= 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: }