using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SMAT_CE.Matlab
{
    /// <summary>
    /// 并行处理
    /// </summary>
    public static class CommonParallel
    {
        /// <summary>
        /// 并行执行操作
        /// </summary>
        /// <param name="actions">操作集合</param>
        public static void Invoke(params Action[] actions)
        {
            if (actions.Length == 0)
            {
                return;
            }
            if (actions.Length == 1)
            {
                actions[0]();
                return;
            }
            if (MathNet.Numerics.Control.MaxDegreeOfParallelism < 2)
            {
                for (int i = 0; i < actions.Length; i++)
                {
                    actions[i]();
                }
                return;
            }
            Parallel.Invoke(CreateParallelOptions(), actions);
        }
        /// <summary>
        /// 并行运行迭代
        /// </summary>
        /// <param name="fromInclusive">分区起始点</param>
        /// <param name="toExclusive">分区结束点</param>
        /// <param name="rangeSize">范围</param>
        /// <param name="body">操作</param>
        public static void For(int fromInclusive, int toExclusive, int rangeSize, Action<int, int> body)
        {
            if (body == null)
            {
                throw new ArgumentNullException("body");
            }
            if (fromInclusive < 0)
            {
                throw new ArgumentOutOfRangeException("fromInclusive");
            }
            if (fromInclusive > toExclusive)
            {
                throw new ArgumentOutOfRangeException("toExclusive");
            }
            if (rangeSize < 1)
            {
                throw new ArgumentOutOfRangeException("rangeSize");
            }
            int num = toExclusive - fromInclusive;
            if (num <= 0)
            {
                return;
            }
            if (MathNet.Numerics.Control.MaxDegreeOfParallelism < 2 || rangeSize * 2 > num)
            {
                body(fromInclusive, toExclusive);
                return;
            }
            Parallel.ForEach<Tuple<int, int>>(Partitioner.Create(fromInclusive, toExclusive, rangeSize), CreateParallelOptions(), delegate(Tuple<int, int> range)
            {
                body(range.Item1, range.Item2);
            });
        }
        /// <summary>
        /// 并行运行迭代
        /// </summary>
        /// <param name="fromInclusive">分区起始点</param>
        /// <param name="toExclusive">分区结束点</param>
        /// <param name="body">操作</param>
        public static void For(int fromInclusive, int toExclusive, Action<int, int> body)
        {
            For(fromInclusive, toExclusive, Math.Max(1, (toExclusive - fromInclusive) / MathNet.Numerics.Control.MaxDegreeOfParallelism), body);
        }
        static ParallelOptions CreateParallelOptions()
        {
            return new ParallelOptions
            {
                MaxDegreeOfParallelism = MathNet.Numerics.Control.MaxDegreeOfParallelism,
                TaskScheduler = MathNet.Numerics.Control.TaskScheduler
            };
        }
    }
}
