/*
* Karinto Library Project
*
* This software is distributed under a zlib-style license.
* See license.txt for more information.
*/
using System;
using System.Collections.Generic;
namespace Karinto
{
///
/// 範囲を示す
///
public class Range
{
#region constructors
///
/// 終端を含む範囲
///
/// 最初の要素
/// 最後の要素
public Range(IComparable first, IComparable last)
: this(first, last, false)
{
}
///
/// 範囲
///
/// 最初の要素
/// 最後の要素
/// 終端を含むか否か(含まないときtrue)
public Range(IComparable first, IComparable last, bool excludeEnd)
{
if (first.GetType() != last.GetType())
{
throw new ArgumentException("The boundary elements must be same type.");
}
First = first;
Last = last;
ExcludesEnd = excludeEnd;
}
#endregion
#region properties
public IComparable First { get; private set; }
public IComparable Last { get; private set; }
public bool ExcludesEnd { get; private set; }
#endregion
#region public methods
///
/// 対象が範囲内か調べる
///
/// 対象
/// 範囲内か否か(範囲内ならtrue)
public bool Includes(IComparable other)
{
if (other.CompareTo(First) < 0) return false;
if (other.CompareTo(Last) > 0) return false;
if (other.CompareTo(Last) == 0) return !ExcludesEnd;
return true;
}
///
/// 両端に値を加算することで範囲を移動させる
///
/// 変化量
public void Shift(double delta)
{
First = (double)First + delta;
Last = (double)Last + delta;
}
///
/// 両端に値を加算することで範囲を移動させる
///
/// 変化量
public void Shift(int delta)
{
First = (int)First + delta;
Last = (int)Last + delta;
}
public IEnumerator GetEnumerator()
{
Int32 cursor = Convert.ToInt32(First);
Int32 last = Convert.ToInt32(Last);
while (cursor < last)
{
yield return cursor;
cursor++;
}
if (cursor == last)
{
if (!ExcludesEnd) yield return cursor;
}
}
///
/// イテレータブロック
///
/// 刻み
/// step刻みの範囲内の要素
public IEnumerable Step(Int32 step)
{
Int32 cursor = Convert.ToInt32(First);
Int32 last = Convert.ToInt32(Last);
while (cursor < last)
{
yield return cursor;
cursor += step;
}
if (cursor == last)
{
if (!ExcludesEnd) yield return cursor;
}
}
///
/// イテレータブロック
///
/// 刻み
/// step刻みの範囲内の要素
public IEnumerable Step(double stepWidth)
{
int i = 0;
double first = Convert.ToDouble(First);
double last = Convert.ToDouble(Last);
double cursor = first;
while (cursor < last)
{
yield return cursor;
i++;
cursor = first + stepWidth * i;//単純に加算していくと誤差が蓄積する
}
if (cursor == last)
{
if (!ExcludesEnd) yield return cursor;
}
}
#endregion
}
}