using System; using Psychlops.Internal; namespace Psychlops { public struct Interval { public enum OPERATOR { CLOSE, OPEN }; public const OPERATOR CLOSE = OPERATOR.CLOSE, OPEN = OPERATOR.OPEN; public struct VAL { public double value; public OPERATOR op; /*public VAL() { val = Double.NaN; op = OPERATOR.CLOSE; }*/ public VAL(double v, OPERATOR o) { value = v; op = o; } public bool bounded() { return !Double.IsNaN(value) && (!Double.IsInfinity(value) || op == OPERATOR.OPEN); } } public VAL begin, end; /*public Interval() { begin = new VAL { val = Double.PositiveInfinity, op = OPERATOR.CLOSE }; end = new VAL { val = Double.NegativeInfinity, op = OPERATOR.CLOSE }; }*/ public Interval(double floor_val, double ceil_val) { begin.value = floor_val; begin.op = OPERATOR.CLOSE; end.value = ceil_val; end.op = OPERATOR.CLOSE; } public Interval(double floor_val, OPERATOR floor_op, double ceil_val, OPERATOR ceil_op) { begin.value = floor_val; begin.op = floor_op; end.value = ceil_val; end.op = ceil_op; } public int int_floor() { double v = Math.ceil(begin.value); if (begin.op == OPEN && v == begin.value) { return (int)v + 1; } else return (int)v; } public int int_floor(int minval) { if(begin.valuemaxval) return maxval; double v = Math.floor(end.value); if (end.op == OPEN && v == end.value) { return (int)v - 1; } else return (int)v; } bool includes(double val) { bool result = false; switch(begin.op) { case OPERATOR.CLOSE: result = begin.value <= val ? true : false; break; case OPERATOR.OPEN: result = begin.value < val ? true : false; break; } switch(end.op) { case OPERATOR.CLOSE: result = result && (end.value >= val ? true : false); break; case OPERATOR.OPEN: result = result && (end.value > val ? true : false); break; } return result; } public bool bounded() { return begin.bounded() && end.bounded(); } System.Collections.Generic.IEnumerable step(double steps) { if (steps > 0) throw new Exception("Interval: step must be a positive"); // return new IntervalIEnumerable(this, steps); Interval it = this; long front_step = (it.begin.op == Interval.OPERATOR.CLOSE ? -1 : 0); long back_step = (long)System.Math.Floor((it.end.value - it.begin.value) / steps); if (it.end.op == Interval.OPERATOR.OPEN && 0 == System.Math.IEEERemainder(it.end.value - it.begin.value, steps)) { back_step -= 1; } while (front_step <= back_step) yield return steps * front_step + it.begin.value; } #region accessor generation public static IntervalAcc operator <(double val, Interval rng) { return new IntervalAcc { instance = new Interval(val, OPERATOR.OPEN, Double.PositiveInfinity, OPERATOR.CLOSE) }; } public static IntervalAcc operator <=(double val, Interval rng) { return new IntervalAcc { instance = new Interval(val, OPERATOR.CLOSE, Double.PositiveInfinity, OPERATOR.CLOSE) }; } public static IntervalAcc operator >(double val, Interval rng) { return new IntervalAcc { instance = new Interval(Double.NegativeInfinity, OPERATOR.CLOSE, val, OPERATOR.OPEN) }; } public static IntervalAcc operator >=(double val, Interval rng) { return new IntervalAcc { instance = new Interval(Double.NegativeInfinity, OPERATOR.CLOSE, val, OPERATOR.CLOSE) }; } public static IntervalAcc operator <(Interval rng, double val) { return new IntervalAcc { instance = new Interval(Double.NegativeInfinity, OPERATOR.CLOSE, val, OPERATOR.OPEN) }; } public static IntervalAcc operator <=(Interval rng, double val) { return new IntervalAcc { instance = new Interval(Double.NegativeInfinity, OPERATOR.CLOSE, val, OPERATOR.CLOSE) }; } public static IntervalAcc operator >(Interval rng, double val) { return new IntervalAcc { instance = new Interval(val, OPERATOR.OPEN, Double.PositiveInfinity, OPERATOR.CLOSE) }; } public static IntervalAcc operator >=(Interval rng, double val) { return new IntervalAcc { instance = new Interval(val, OPERATOR.CLOSE, Double.PositiveInfinity, OPERATOR.CLOSE) }; } #endregion } namespace Internal { #region accessor definition public struct IntervalAcc { public Interval instance; public static IntervalAcc operator <(double val, IntervalAcc rng) { return new IntervalAcc { instance = new Interval(val, Interval.OPERATOR.OPEN, rng.instance.end.value, rng.instance.end.op) }; } public static IntervalAcc operator <=(double val, IntervalAcc rng) { return new IntervalAcc { instance = new Interval(val, Interval.OPERATOR.CLOSE, rng.instance.end.value, rng.instance.end.op) }; } public static IntervalAcc operator >(double val, IntervalAcc rng) { return new IntervalAcc { instance = new Interval(rng.instance.begin.value, rng.instance.begin.op, val, Interval.OPERATOR.OPEN) }; } public static IntervalAcc operator >=(double val, IntervalAcc rng) { return new IntervalAcc { instance = new Interval(rng.instance.begin.value, rng.instance.begin.op, val, Interval.OPERATOR.CLOSE) }; } public static IntervalAcc operator <(IntervalAcc rng, double val) { return new IntervalAcc { instance = new Interval(rng.instance.begin.value, rng.instance.begin.op, val, Interval.OPERATOR.OPEN) }; } public static IntervalAcc operator <=(IntervalAcc rng, double val) { return new IntervalAcc { instance = new Interval(rng.instance.begin.value, rng.instance.begin.op, val, Interval.OPERATOR.CLOSE) }; } public static IntervalAcc operator >(IntervalAcc rng, double val) { return new IntervalAcc { instance = new Interval(val, Interval.OPERATOR.OPEN, rng.instance.end.value, rng.instance.end.op) }; } public static IntervalAcc operator >=(IntervalAcc rng, double val) { return new IntervalAcc { instance = new Interval(val, Interval.OPERATOR.CLOSE, rng.instance.end.value, rng.instance.end.op) }; } public static implicit operator Interval(IntervalAcc rhs) { return rhs.instance; } } #endregion } }