Skip to content

Instantly share code, notes, and snippets.

@AdamWhiteHat
Created June 28, 2023 17:45
Show Gist options
  • Save AdamWhiteHat/728186383f61dd6aab2134f937393cdd to your computer and use it in GitHub Desktop.
Save AdamWhiteHat/728186383f61dd6aab2134f937393cdd to your computer and use it in GitHub Desktop.
Interval arithmetic type class
/// <summary>
/// Interval arithmetic type class
/// </summary>
public class Interval : IEquatable<Interval>, IComparable<Interval>, IComparable
{
#region Properties
public static Interval Zero;
public static Interval One;
public BigInteger Min { get; private set; }
public BigInteger Max { get; private set; }
public BigInteger Size { get { return Max - Min; } }
public BigInteger ArithmeticAverage { get { return (Min + Max) / 2; } }
//public BigInteger GeometricAverage { get { return (Min * Max).SquareRoot(); } }
#endregion
#region Constructors
public Interval() : this(0) { }
public Interval(BigInteger value) : this(value, value) { }
public Interval(BigInteger min, BigInteger max)
{
Min = min;
Max = max;
}
static Interval()
{
Zero = new Interval(0);
One = new Interval(1);
}
public static Interval Combine(Interval left, Interval right)
{
if (Interval.IsDisjoint(left, right)) { throw new ArgumentOutOfRangeException($"Parameters {nameof(left)} and {nameof(right)} must overlap."); }
Interval first = left;
Interval second = right;
if (right < left)
{
first = right;
second = left;
}
return new Interval(BigInteger.Min(first.Min, second.Min), BigInteger.Max(first.Max, second.Max));
}
#endregion
#region Operations
public static Interval Add(Interval left, Interval right) => new Interval((left.Min + right.Min), (left.Max + right.Max));
public static Interval Subtract(Interval left, Interval right) => new Interval((left.Min - right.Max), (left.Max - right.Min));
public static Interval Divide(Interval left, Interval right) => new Interval(left.Min / right.Max, left.Max / right.Min);
public static Interval Multiply(Interval left, Interval right) =>
new Interval(
CollectionMin(left.Min * right.Min, left.Min * right.Max, left.Max * right.Min, left.Max * right.Max),
CollectionMax(left.Min * right.Min, left.Min * right.Max, left.Max * right.Min, left.Max * right.Max)
);
public static Interval Negate(Interval value) => Interval.Subtract(Interval.Zero, value);
public static Interval Clone(Interval value) => new Interval(value.Min, value.Max);
private static BigInteger CollectionMin(params BigInteger[] elements) { return elements.Min(); }
private static BigInteger CollectionMax(params BigInteger[] elements) { return elements.Max(); }
#endregion
#region Operators
#region Arithmetic Operators
public static Interval operator +(Interval left, Interval right) => Interval.Add(left, right);
public static Interval operator -(Interval left, Interval right) => Interval.Subtract(left, right);
public static Interval operator *(Interval left, Interval right) => Interval.Multiply(left, right);
public static Interval operator /(Interval left, Interval right) => Interval.Divide(left, right);
public static Interval operator -(Interval value) => Interval.Negate(value);
#endregion
#region Comparison Operators
public static bool operator ==(Interval left, Interval right) => Interval.Equals(left, right);
public static bool operator !=(Interval left, Interval right) => !Interval.Equals(left, right);
public static bool operator <(Interval left, Interval right) => (left.Min <= right.Min) && (left.Max < right.Max);
public static bool operator >(Interval left, Interval right) => (right.Max >= left.Max) && (right.Min > left.Min);
public static bool operator <=(Interval left, Interval right) => (left < right) || (left.Max == right.Max);
public static bool operator >=(Interval left, Interval right) => (right > left) || (right.Min == left.Min);
#endregion
#region Conversion Operators
public static implicit operator Interval(int value) => new Interval(value);
public static implicit operator Interval(BigInteger value) => new Interval(value);
#endregion
#endregion
#region Equality / CompareTo
public static bool Equals(Interval left, Interval right)
{
return (left.Min == right.Min && left.Max == right.Max);
}
public bool Equals(Interval other)
{
return this.Equals(other);
}
public int CompareTo(object obj)
{
return this.CompareTo(obj as Interval);
}
public int CompareTo(Interval other)
{
if (Interval.Equals(this, other)) { return 0; }
else if (this > other) { return 1; }
else if (this < other) { return -1; }
else if (this >= other) { return 1; }
else if (this <= other) { return -1; }
else { throw new Exception(); }
}
#endregion
#region Membership
public bool Contains(BigInteger value)
{
return (value >= this.Min && value <= this.Max);
}
public static bool IsDisjoint(Interval left, Interval right)
{
return !(left.Contains(right.Min) || left.Contains(right.Max));
}
#endregion
#region Overrides
public override bool Equals(object obj)
{
return Interval.Equals(this, obj as Interval);
}
public override int GetHashCode()
{
return new Tuple<BigInteger, BigInteger>(this.Min, this.Max).GetHashCode();
}
public override string ToString()
{
if (Min == Max)
{
return $"{Min}";
}
else
{
return $"[{Min},{Max}]";
}
}
#endregion
}
public static class IntervalExtensionMethods
{
public static bool ContainsZero(this Interval source)
{
return (source.Min.Sign != source.Max.Sign);
}
public static Interval MiddleThird(this Interval source)
{
BigInteger oneThird = DivideInterval(source, 3);
return new Interval(source.Min + oneThird, source.Max - oneThird);
}
public static (Interval, Interval) Bisect(this Interval source)
{
BigInteger midPoint = source.MidPoint();
Interval left = new Interval(source.Min, midPoint);
Interval right = new Interval(midPoint, source.Max);
return (left, right);
}
public static BigInteger MidPoint(this Interval source)
{
return DivideInterval(source, 2);
}
public static BigInteger DivideInterval(this Interval source, BigInteger divisor)
{
BigInteger adjust = -(source.Min);
BigInteger min = source.Min + adjust;
BigInteger max = source.Max + adjust;
BigInteger result = (max - min) / divisor;
result = result - adjust;
return result;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment