Sparse Double Range : Number « Data Types « C# / C Sharp






Sparse Double Range

   
//http://isotopescreencapture.codeplex.com/
//The MIT License (MIT)
using System.Collections.Generic;
using System.Linq;

namespace Isotope.Collections.Ranges
{
    public static partial class EnumerableUtil
    {
        public static IEnumerable<T> Single<T>(T item)
        {
            yield return item;
        }




        /// <summary>
        /// Given a range (start,end) and a number of steps, will yield that a number for each step
        /// </summary>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <param name="steps"></param>
        /// <returns></returns>
        public static IEnumerable<double> RangeSteps(double start, double end, int steps)
        {
            // for non-positive number of steps, yield no points
            if (steps < 1)
            {
                yield break;
            }

            // for exactly 1 step, yield the start value
            if (steps == 1)
            {
                yield return start;
                yield break;
            }

            // for exactly 2 stesp, yield the start value, and then the end value
            if (steps == 2)
            {
                yield return start;
                yield return end;
                yield break;
            }

            // for 3 steps or above, start yielding the segments
            // notice that the start and end values are explicitly returned so that there
            // is no possibility of rounding error affecting their values
            int segments = steps - 1;
            double total_length = end - start;
            double stepsize = total_length / segments;
            yield return start;
            for (int i = 1; i < (steps - 1); i++)
            {
                double p = start + (stepsize * i);
                yield return p;
            }
            yield return end;
        }

        public static IEnumerable<TGROUP> GroupByCount<T, TGROUP>(
            IEnumerable<T> items,
            int group_size,
            System.Func<int, TGROUP> func_new_col,
            System.Action<TGROUP, int, T> func_add) where TGROUP : class
        {


            if (items == null)
            {
                throw new System.ArgumentNullException("items");
            }

            if (group_size < 1)
            {
                throw new System.ArgumentOutOfRangeException("group_size");
            }

            if (func_new_col == null)
            {
                throw new System.ArgumentNullException("func_new_col");
            }


            if (func_add == null)
            {
                throw new System.ArgumentNullException("func_add");
            }



            int cur_group_size = 0;
            TGROUP cur_group = null;
            foreach (var item in items)
            {
                if (cur_group_size == 0)
                {
                    if (cur_group == null)
                    {
                        cur_group = func_new_col(group_size);
                    }
                    else
                    {
                        throw new System.InvalidOperationException();
                    }
                }

                func_add(cur_group, cur_group_size, item);
                cur_group_size++;
                if (cur_group_size == group_size)
                {

                    yield return cur_group;
                    cur_group = null;
                    cur_group_size = 0;
                }

            }

            if (cur_group_size > 0)
            {
                if (cur_group == null)
                {
                    throw new System.InvalidOperationException();
                }
                yield return cur_group;
            }

        }

        public static IEnumerable<TGROUP> GroupByCount<T, TGROUP>(ICollection<T> items, ICollection<int> group_sizes, System.Func<int, TGROUP> func_new_col, System.Action<TGROUP, int, T> func_add)
        {


            if (items == null)
            {
                throw new System.ArgumentNullException("items");
            }

            if (group_sizes == null)
            {
                throw new System.ArgumentNullException("group_sizes");
            }

            if (func_new_col == null)
            {
                throw new System.ArgumentNullException("func_new_col");
            }


            if (func_add == null)
            {
                throw new System.ArgumentNullException("func_add");
            }



            int total_group_sizes = group_sizes.Sum();
            if (total_group_sizes != items.Count)
            {
                throw new System.ArgumentException("group_sizes must account for all items");
            }

            int items_added = 0;
            for (int group_index = 0; group_index < group_sizes.Count; group_index++)
            {
                int cur_group_size = group_sizes.ElementAt(group_index);

                if (cur_group_size < 0)
                {
                    throw new System.ArgumentException("group_sizes contains a negative numver");
                }
                var cur_group = func_new_col(cur_group_size);
                for (int row_index = 0; row_index < cur_group_size; row_index++)
                {
                    var cur_item = items.ElementAt(items_added);
                    func_add(cur_group, row_index, cur_item);
                    items_added++;
                }
                yield return cur_group;

            }

        }


        public static IDictionary<K, List<V>> Bucketize<K, V>(IEnumerable<V> items, System.Func<V, K> func_get_key, IEqualityComparer<K> ieq)
        {
            if (items == null)
            {
                throw new System.ArgumentNullException("items");
            }

            if (func_get_key == null)
            {
                throw new System.ArgumentNullException("func_get_key");
            }

            var dic = new Dictionary<K, List<V>>(ieq);
            foreach (var item in items)
            {
                var key = func_get_key(item);
                List<V> list = null;
                bool found = dic.TryGetValue(key, out list);
                if (!found)
                {
                    list = new List<V>();
                    dic[key] = list;
                }
                list.Add(item);

            }

            return dic;
        }


        public static IDictionary<K, List<V>> Bucketize<K, V>(IEnumerable<V> items, System.Func<V, K> func_get_key)
        {
            IEqualityComparer<K> ieq = null;
            return Bucketize<K, V>(items, func_get_key, ieq);
        }


        public static IDictionary<K, int> Histogram<K, V>(IEnumerable<V> items, System.Func<V, K> func_get_key, IEqualityComparer<K> ieq)
        {
            if (items == null)
            {
                throw new System.ArgumentNullException("items");
            }

            if (func_get_key == null)
            {
                throw new System.ArgumentNullException("func_get_key");
            }

            var dic = new Dictionary<K, int>(ieq);
            foreach (var item in items)
            {
                var key = func_get_key(item);
                int old_value = 0;
                bool found = dic.TryGetValue(key, out old_value);
                if (!found)
                {
                    dic[key] = 1;
                }
                else
                {
                    dic[key] = old_value + 1;
                }

            }

            return dic;
        }

        public static IDictionary<T, int> Histogram<T>(IEnumerable<T> items)
        {
            var dic = Histogram(items, i => i, null);
            return dic;
        }

        public static List<List<T>> Chunkify<T>(IEnumerable<T> items, int chunksize)
        {
            var chunks = new List<List<T>>();
            List<T> cur_chunk = null;
            Chunkify(items, chunksize,
                () =>
                {
                    cur_chunk = new List<T>(chunksize); chunks.Add(cur_chunk);
                },
                item =>
                {
                    cur_chunk.Add(item);
                });

            return chunks;
        }

        public static void Chunkify<T>(IEnumerable<T> items, int chunksize, System.Action create_chunk, System.Action<T> add_item)
        {
            if (items == null)
            {
                throw new System.ArgumentNullException("items");
            }

            if (chunksize < 1)
            {
                throw new System.ArgumentOutOfRangeException("chunksize");
            }

            int item_count = 0;
            int curchunk_size = 0;
            foreach (T item in items)
            {
                if ((item_count % chunksize) == 0)
                {
                    create_chunk();
                    curchunk_size = 0;
                }
                add_item(item);
                item_count++;
                curchunk_size++;
            }

        }
    }
    public struct DoubleRange
    {
        public readonly double _Lower;
        public readonly double _Upper;

        public double Lower
        {
            get { return this._Lower; }
        }

        public double Upper
        {
            get { return this._Upper; }
        }

        private DoubleRange(double lower, double upper)
        {
            this._Lower = lower;
            this._Upper = upper;
        }

        /// <summary>
        /// Creates a range from the lower and upper values
        /// </summary>
        /// <example>
        /// (0,0) -> [0]
        /// (0,1) -> [0,1]
        /// (0,5) -> [0,1,2,3,4,5]
        /// (2,5) -> [2,3,4,5]
        /// </example>
        /// <param name="lower"></param>
        /// <param name="upper"></param>
        /// <returns></returns>
        public static DoubleRange FromEndpoints(double lower, double upper)
        {
            return new DoubleRange(lower, upper);
        }

        public double Length
        {
            get { return this.Upper - this.Lower; }
        }

        public override string ToString()
        {
            var invariant_culture = System.Globalization.CultureInfo.InvariantCulture;
            return string.Format(invariant_culture, "Range({0},{1})", this.Lower, this.Upper);
        }

        private static bool _intersects_exclusive(DoubleRange range1, DoubleRange range2)
        {
            bool val = (range1.Lower < range2.Lower) && (range1.Upper > range2.Lower);
            return val;
        }

        private static bool _intersects_inclusive(DoubleRange range1, DoubleRange range2)
        {
            bool val = (range1.Lower <= range2.Lower) && (range1.Upper >= range2.Upper);
            return val;
        }

        /// <summary>
        /// Tests if this range interests with another
        /// </summary>
        /// <param name="range">the other range</param>
        /// <returns>true if they intersect</returns>
        public bool IntersectsExclusive(DoubleRange range)
        {
            bool val = _intersects_exclusive(this, range) || _intersects_exclusive(range, this);
            return val;
        }

        public bool IntersectsInclusive(DoubleRange range)
        {
            bool val = _intersects_inclusive(this, range) || _intersects_inclusive(range, this);
            return val;
        }

        private static bool _touches(DoubleRange range1, DoubleRange range2)
        {
            var val = (range1.Upper == range2.Lower);
            return val;
        }

        /// <summary>
        /// Tests if this range touches another. For example (1-2) touches (3,5) but (1,2) does not touch (4,5)
        /// </summary>
        /// <param name="range">the other range</param>
        /// <returns>true if they touch</returns>
        public bool Touches(DoubleRange range)
        {
            var val = _touches(this, range) || _touches(range, this);
            return val;
        }

        /// <summary>
        /// Tests if this range contains a specific double
        /// </summary>
        /// <param name="n">the double</param>
        /// <returns>true if the number is contained</returns>
        public bool Contains(double n)
        {
            return (this.Lower <= n) && (n <= this.Upper);
        }

        /// <summary>
        /// Join this range with another and return a single range that contains them both. The ranges must either touch or interest.
        /// for example (0,2) amd (3,7) will yield (0,7)
        /// </summary>
        /// <param name="range">the other range</param>
        /// <returns>the merged range</returns>
        public DoubleRange JoinWith(DoubleRange range)
        {
            if (this.IntersectsExclusive(range) || this.Touches(range))
            {
                double new_Upper = System.Math.Max(this.Upper, range.Upper);
                double new_Lower = System.Math.Min(this.Lower, range.Lower);
                return DoubleRange.FromEndpoints(new_Lower, new_Upper);
            }
            else
            {
                throw new System.ArgumentException("Ranges cannot be joined because they do not touch or overlap");
            }
        }

        public IEnumerable<double> Values
        {
            get
            {
                double step = 1.0;
                return this.GetValues(step);
            }
        }

        public IEnumerable<double> GetValues(double step)
        {
            if (step <= 0.0)
            {
                throw new System.ArgumentOutOfRangeException("step", "must be positive");
            }

            double i = this.Lower;
            while (i <= this.Upper)
            {
                yield return i;
                i += step;
            }
        }
    }

    public class SparseDoubleRange
    {
        private List<DoubleRange> ranges;

        public SparseDoubleRange()
        {
            this.clear();
        }

        public IEnumerable<DoubleRange> Ranges
        {
            get
            {
                foreach (var range in this.ranges)
                {
                    yield return range;
                }
            }
        }

        public double Count
        {
            get
            {
                double length = this.ranges.Aggregate(0.0, (old, rng) => old + rng.Length);
                return length;
            }
        }

        private void clear()
        {
            this.ranges = new List<DoubleRange>();
        }

        public int RangeCount
        {
            get { return this.ranges.Count; }
        }

        public void AddInclusive(double lower, double upper)
        {
            var rng = DoubleRange.FromEndpoints(lower, upper);
            this.Add(rng);
        }

        public void Add(DoubleRange range)
        {
            var left = new List<DoubleRange>();
            var right = new List<DoubleRange>();
            foreach (var rng in this.ranges)
            {
                if (range.IntersectsExclusive(rng) || range.Touches(rng))
                {
                    range = range.JoinWith(rng);
                }
                else if (rng.Upper < range.Lower)
                {
                    left.Add(rng);
                }
                else if (range.Upper < rng.Lower)
                {
                    right.Add(rng);
                }
                else
                {
                    throw new System.InvalidOperationException("Internal Error");
                }
            }

            this.ranges = left.Concat(EnumerableUtil.Single(range)).Concat(right).ToList();
        }

        public double Lower
        {
            get
            {
                if (this.ranges.Count < 1)
                {
                    throw new System.InvalidOperationException("empty");
                }

                return this.ranges[0].Lower;
            }
        }

        public double Upper
        {
            get
            {
                if (this.ranges.Count < 1)
                {
                    throw new System.InvalidOperationException("empty");
                }

                return this.ranges[this.ranges.Count - 1].Upper;
            }
        }

        public void RemoveInclusive(int lower, int upper)
        {
            var rng = DoubleRange.FromEndpoints(lower, upper);
            this.RemoveInclusive(rng);
        }

        public void RemoveExclusive(int lower, int upper)
        {
            if ((upper - lower) > (2 * double.Epsilon))
            {
                var rng = DoubleRange.FromEndpoints(lower + double.Epsilon, upper - double.Epsilon);
                this.RemoveInclusive(rng);
            }
        }

        public void RemoveInclusive(DoubleRange range)
        {
            // if the range doesn't intersect this collection do nothing
            if (!range.IntersectsInclusive(DoubleRange.FromEndpoints(this.Lower, this.Upper)))
            {
                return;
            }

            var middle = new List<DoubleRange>();

            foreach (var S in this.ranges)
            {
                if (!range.IntersectsInclusive(S))
                {
                    middle.Add(S);
                    continue;
                }

                if ((range.Lower <= S.Lower) && (range.Upper >= S.Upper))
                {
                    // disregard S completely
                    continue;
                }

                if (range.Lower > S.Lower)
                {
                    if (S.Lower <= (range.Lower - double.Epsilon))
                    {
                        var X = DoubleRange.FromEndpoints(S.Lower, range.Lower);
                        middle.Add(X);
                    }
                }

                if (range.Upper <= S.Upper)
                {
                    if ((range.Upper + double.Epsilon) <= S.Upper)
                    {
                        var X = DoubleRange.FromEndpoints(range.Upper, S.Upper);
                        middle.Add(X);
                    }
                }
                else
                {
                    throw new System.InvalidOperationException("internal error");
                }
            }

            this.ranges = middle;
        }

        public DoubleRange? FindRangeContainingNumber(double n)
        {
            foreach (var rng in this.ranges)
            {
                if (rng.Contains(n))
                {
                    return rng;
                }
            }

            return null;
        }

        public bool Contains(double n)
        {
            var rng = this.FindRangeContainingNumber(n);
            return rng != null ? true : false;
        }

        public override string ToString()
        {
            var sb = new System.Text.StringBuilder();
            sb.AppendFormat("{0}(", this.GetType().Name);
            foreach (var rng in this.ranges)
            {
                sb.Append(rng.ToString());
            }

            sb.Append(")");
            return sb.ToString();
        }

        public IEnumerable<double> Values
        {
            get
            {
                foreach (var rng in this.Ranges)
                {
                    foreach (int i in rng.Values)
                    {
                        yield return i;
                    }
                }
            }
        }

        public IEnumerable<double> GetValues(double step)
        {
            foreach (var rng in this.Ranges)
            {
                foreach (double i in rng.GetValues(step))
                {
                    yield return i;
                }
            }
        }
    }
}

   
    
    
  








Related examples in the same category

1.Converting Degrees to RadiansConverting Degrees to Radians
2.Converting Radians to DegreesConverting Radians to Degrees
3.Converting a Number in Another Base to Base10Converting a Number in Another Base to Base10
4.Determining if a String is a Valid Number by Parse functionsDetermining if a String is a Valid Number by Parse functions
5.Use regualr expression to check: is it a numberUse regualr expression to check: is it a number
6.Use int.Parse to check: is it an integerUse int.Parse to check: is it an integer
7.Use Integer.Parse to check: is it a numberUse Integer.Parse to check: is it a number
8.Use regualr expression to check: Is it an Unsigned IntegerUse regualr expression to check: Is it an Unsigned Integer
9.Use regular expression to get number from stringUse regular expression to get number from string
10.Faster way to get number from stringFaster way to get number from string
11.Converting Celsius to FahrenheitConverting Celsius to Fahrenheit
12.Converting Fahrenheit to CelsiusConverting Fahrenheit to Celsius
13.Is it a double numberIs it a double number
14.Test for an Even or Odd ValueTest for an Even or Odd Value
15.System maximums and minimumsSystem maximums and minimums
16.Declare int and use itDeclare int and use it
17.Use int variableUse int variable
18.shows that using an instance of the System.Int32 stucture is the same as using the int keywordshows that using an instance of the System.Int32 stucture is the same as using the int keyword
19.Numeric Parsing DemoNumeric Parsing Demo
20.Number calculation utils
21.Double Range
22.Int Range
23.Sparse Int Range
24.Checks if a value is in a range (inclusive)
25.Determines whether the specified value is null.
26.Converts specified value to nullable value.
27.Validate number
28.Native SizeOf
29.Is Numeric