using Misc;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FLY.FilmCasting.AutoDie.Common
{
    public static class MyMath
    {
        #region 数列操作
        /// <summary>
        /// 转为 % 数据，单位 %
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static int[] GetPercent(int[] data)
        {
            int avg = Misc.MyMath.Avg(data);

            int[] percent = new int[data.Count()];
            for (int i = 0; i < data.Count(); i++)
            {
                if (Misc.MyBase.ISVALIDATA(data[i]))
                {
                    percent[i] = 100 * (data[i] - avg) / avg;
                }
                else
                {
                    percent[i] = Misc.MyBase.NULL_VALUE;
                }
            }
            return percent;
        }
        /// <summary>
        /// 转为 % 数据，单位 %
        /// </summary>
        /// <param name="datas"></param>
        /// <returns></returns>
        public static double[] GetPercent(IEnumerable<double> datas)
        {
            double[] percent = new double[datas.Count()];

            double avg = datas.AverageNoNull();
            if (double.IsNaN(avg))
            {
                for (int i = 0; i < percent.Count(); i++) {
                    percent[i] = double.NaN;
                }
                return percent;
            }
            else
            {
                for (int i = 0; i < datas.Count(); i++)
                {
                    double d = datas.ElementAt(i);
                    if (double.IsNaN(d))
                        percent[i] = double.NaN;
                    else
                        percent[i] = 100 * (d - avg) / avg;
                }
            }
            return percent;
        }


        /// <summary>
        /// 两列数据相减
        /// </summary>
        /// <param name="data1"></param>
        /// <param name="data2"></param>
        /// <returns></returns>
        public static int[] GetDiff(int[] data1, int[] data2)
        {
            int[] diff = new int[data1.Count()];
            for (int i = 0; i < data1.Count(); i++)
            {
                if (Misc.MyBase.ISVALIDATA(data1[i]) && Misc.MyBase.ISVALIDATA(data2[i]))
                {
                    diff[i] = data1[i] - data2[i];
                }
                else
                {
                    diff[i] = Misc.MyBase.NULL_VALUE;
                }
            }
            return diff;
        }
        /// <summary>
        /// 两列数据相减
        /// </summary>
        /// <param name="data1"></param>
        /// <param name="data2"></param>
        /// <returns></returns>
        public static double[] GetDiff(double[] data1, double[] data2)
        {
            double[] diff = new double[data1.Count()];
            for (int i = 0; i < data1.Count(); i++)
            {
                if (double.IsNaN(data1[i]) || double.IsNaN(data2[i]))
                    diff[i] = double.NaN;
                else
                    diff[i] = data1[i] - data2[i];
            }
            return diff;
        }
        /// <summary>
        /// 两列数据中间值
        /// </summary>
        /// <param name="data1"></param>
        /// <param name="data2"></param>
        /// <returns></returns>
        public static int[] GetMid(int[] data1, int[] data2)
        {
            int[] mid = new int[data1.Count()];
            for (int i = 0; i < data1.Count(); i++)
            {
                if (Misc.MyBase.ISVALIDATA(data1[i]) && Misc.MyBase.ISVALIDATA(data2[i]))
                {
                    mid[i] = (data1[i] + data2[i]) / 2;
                }
                else
                {
                    mid[i] = Misc.MyBase.NULL_VALUE;
                }
            }
            return mid;
        }
        /// <summary>
        /// 上下平移，使平均值为0
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static int[] OffsetAvgBe0(int[] data)
        {
            int avg = Misc.MyMath.Avg(data);

            int[] data_out = new int[data.Count()];
            for (int i = 0; i < data.Count(); i++)
            {
                if (Misc.MyBase.ISVALIDATA(data[i]))
                {
                    data_out[i] = data[i] - avg;
                }
                else
                {
                    data_out[i] = Misc.MyBase.NULL_VALUE;
                }
            }
            return data_out;
        }
        /// <summary>
        /// 上下平移，使平均值为0
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static double[] OffsetAvgBe0(double[] datas)
        {
            double[] datas_out = new double[datas.Count()];

            double avg = datas.AverageNoNull();
            if (double.IsNaN(avg)) {
                for (int i = 0; i < datas.Count(); i++)
                    datas_out[i] = double.NaN;
            }
           
            for (int i = 0; i < datas.Count(); i++)
            {
                if (double.IsNaN(datas[i]))
                    datas_out[i] = double.NaN;
                else
                    datas_out[i] = datas[i] - avg;
            }
            return datas_out;
        }


        /// <summary>
        /// 放大数量
        /// </summary>
        /// <param name="data"></param>
        /// <param name="z"></param>
        /// <returns></returns>
        public static T[] ZoomIn<T>(T[] data, int z)
        {
            if (z == 1)
            {
                return data.Clone() as T[];
            }
            T[] data_out = new T[data.Count() * z];
            for (int i = 0; i < data.Count(); i++)
            {
                for (int j = 0; j < z; j++)
                    data_out[i * z + j] = data[i];
            }
            return data_out;

        }

        /// <summary>
        /// 缩小数量
        /// </summary>
        /// <param name="data"></param>
        /// <param name="z"></param>
        /// <returns></returns>
        public static int[] ZoomOut(int[] data, int z)
        {
            if (z == 1)
            {
                return data.Clone() as int[];
            }
            int[] data_out = new int[data.Count() / z];
            for (int i = 0; i < data_out.Count(); i++)
            {
                data_out[i] = Misc.MyMath.Avg(data, i * z, (i + 1) * z - 1);
            }
            return data_out;
        }

        /// <summary>
        /// 缩小数量
        /// </summary>
        /// <param name="data"></param>
        /// <param name="z"></param>
        /// <returns></returns>
        public static double[] ZoomOut(double[] data, int z)
        {
            if (z == 1)
            {
                return data.Clone() as double[];
            }
            double[] data_out = new double[data.Count() / z];
            for (int i = 0; i < data_out.Count(); i++)
            {
                data_out[i] = Misc.MyMath.Avg(data, i * z, (i + 1) * z - 1);
            }
            return data_out;
        }
        /// <summary>
        /// 滤波操作
        /// </summary>
        /// <param name="data">数据源</param>
        /// <param name="cell">滤波器</param>
        /// <returns></returns>
        public static int[] Filter(int[] data, int[] cell)
        {
            if (cell == null || cell.Count()==0)
            {
                return data.Clone() as int[];
            }
            int[] data_out = new int[data.Count()];

            for (int i = 0; i < data.Count(); i++)
            {
                int sum = 0;
                int cnt = 0;
                for (int j = 0; j < cell.Count(); j++)
                {
                    int idx = i - cell.Count() / 2 + j;
                    if (idx < 0)
                        idx += data.Count();
                    else if (idx >= data.Count())
                        idx -= data.Count();
                    if (Misc.MyBase.ISVALIDATA(data[idx]))
                    {
                        sum += data[idx] * cell[j];
                        cnt += cell[j];
                    }
                }
                if (cnt > 0)
                {
                    data_out[i] = sum / cnt;
                }
                else
                {
                    data_out[i] = Misc.MyBase.NULL_VALUE;
                }
            }
            return data_out;
        }

        /// <summary>
        /// 滤波操作
        /// </summary>
        /// <param name="data">数据源</param>
        /// <param name="cell">滤波器</param>
        /// <returns></returns>
        public static double[] Filter(IEnumerable<double> data, IEnumerable<double> cell)
        {
            if (cell == null || cell.Count() == 0)
            {
                return data.ToArray();
            }
            double[] data_out = new double[data.Count()];

            for (int i = 0; i < data.Count(); i++)
            {
                double sum = 0;
                double cnt = 0;
                for (int j = 0; j < cell.Count(); j++)
                {
                    int idx = i - cell.Count() / 2 + j;
                    if (idx < 0)
                        idx += data.Count();
                    else if (idx >= data.Count())
                        idx -= data.Count();
                    if(!double.IsNaN(data.ElementAt(idx)))
                    {
                        sum += data.ElementAt(idx) * cell.ElementAt(j);
                        cnt += cell.ElementAt(j);
                    }
                }
                if (cnt > 0)
                {
                    data_out[i] = sum / cnt;
                }
                else
                {
                    data_out[i] = double.NaN;
                }
            }
            return data_out;
        }

        /// <summary>
        /// 数据 放大
        /// </summary>
        /// <param name="data"></param>
        /// <param name="z">放大倍数</param>
        /// <returns></returns>
        public static int[] ZoomY(int[] data, double z)
        {
            if (z == 1 )
            {
                return data.Clone() as int[];
            }
            int[] data_out = new int[data.Count()];

            for (int i = 0; i < data.Count(); i++)
            {
                if (Misc.MyBase.ISVALIDATA(data[i]))
                {
                    data_out[i] = (int)(data[i] * z);
                }
                else
                {
                    data_out[i] = Misc.MyBase.NULL_VALUE;
                }
            }
            return data_out;
        }
        /// <summary>
        /// 滤波操作，均值滤波
        /// </summary>
        /// <param name="data">数据源</param>
        /// <param name="cell">滤波器宽度</param>
        /// <returns></returns>
        public static int[] Filter(int[] data, int cell_width)
        {

            int[] data_out = new int[data.Count()];

            for (int i = 0; i < data.Count(); i++)
            {
                int sum = 0;
                int cnt = 0;
                for (int j = 0; j < cell_width; j++)
                {
                    int idx = i - cell_width / 2 + j;
                    if (idx < 0)
                        idx += data.Count();
                    else if (idx >= data.Count())
                        idx -= data.Count();
                    if (Misc.MyBase.ISVALIDATA(data[idx]))
                    {
                        sum += data[idx];
                        cnt += 1;
                    }
                }
                if (cnt > 0)
                {
                    data_out[i] = sum / cnt;
                }
                else
                {
                    data_out[i] = Misc.MyBase.NULL_VALUE;
                }
            }
            return data_out;
        }
        /// <summary>
        /// 通过data2 平移，找到与 data1 最相似的位置， data1 与 data2 必须大小一致
        /// </summary>
        /// <param name="data1"></param>
        /// <param name="data2"></param>
        /// <param name="range_percent">0~1</param>
        /// <param name="offset"></param>
        /// <param name="r"></param>
        public static void CalBestMove(int[] data1, int[] data2, double range_percent, out int data2_move, out double max_r)
        {
            if (data1.Length != data2.Length)
            {
                throw new Exception("CalBestMove() 参数错误 (data1.Length = " + data1.Length.ToString() + ")!=(data2.Length =" + data2.Length.ToString() + ")");
            }

            if ((range_percent > 1) || (range_percent < 0))
            {
                throw new Exception("CalBestMove() 参数错误 range_percent = " + range_percent.ToString() + " 异常");
            }
            int range = (int)(Math.Ceiling(range_percent * data1.Length));

            if (range <= 0)
                range = 1;


            double mr = 0;
            int mi = -1;
            for (int i = -range; i <= range; i++)
            {
                int[] data22 = Move(data2, i);
                double r = Misc.MyMath.Correl(data1, data22);
                if (mi == -1)
                {
                    mr = r;
                    mi = i;
                }
                else
                {
                    if (r > mr)
                    {
                        mr = r;
                        mi = i;
                    }
                }

            }

            //找到了！！！

            max_r = mr;
            data2_move = mi;
        }

        /// <summary>
        /// 通过data2 平移，找到与 data1 最相似的位置， data1 与 data2 必须大小一致
        /// </summary>
        /// <param name="data1"></param>
        /// <param name="data2"></param>
        /// <param name="range_percent">0~1</param>
        /// <param name="offset"></param>
        /// <param name="r"></param>
        public static void CalBestMove(double[] data1, double[] data2, double range_percent, out int data2_move, out double max_r)
        {
            if (data1.Length != data2.Length)
            {
                throw new Exception("CalBestMove() 参数错误 (data1.Length = " + data1.Length.ToString() + ")!=(data2.Length =" + data2.Length.ToString() + ")");
            }

            if ((range_percent > 1) || (range_percent < 0))
            {
                throw new Exception("CalBestMove() 参数错误 range_percent = " + range_percent.ToString() + " 异常");
            }
            int range = (int)(Math.Ceiling(range_percent * data1.Length));

            if (range <= 0)
                range = 1;


            double mr = 0;
            int mi = -1;
            for (int i = -range; i <= range; i++)
            {
                var data22 = Move(data2, i);
                double r = Misc.MyMath.Correl(data1, data22);
                if (mi == -1)
                {
                    mr = r;
                    mi = i;
                }
                else
                {
                    if (r > mr)
                    {
                        mr = r;
                        mi = i;
                    }
                }

            }

            //找到了！！！

            max_r = mr;
            data2_move = mi;
        }

        /// <summary>
        /// 平移
        /// </summary>
        /// <param name="data">原始厚度数组</param>
        /// <param name="move">平移量 向右移动为正</param>
        public static int[] Move(int[] data, int move)
        {
            if (move == 0)
            {
                //什么都不用做
                return data.Clone() as int[];
            }
            int cnt = data.Count();
            int[] data_out = new int[cnt];


            for (int i = 0; i < cnt; i++)
            {
                int idx = i - move;
                if (idx >= cnt)
                    idx -= cnt;
                else if (idx < 0)
                    idx += cnt;

                data_out[i] = data[idx];

            }
            return data_out;

        }

        /// <summary>
        /// 平移
        /// </summary>
        /// <param name="data">原始厚度数组</param>
        /// <param name="move">平移量 向右移动为正</param>
        public static T[] Move<T>(T[] data, int move)
        {
            if (move == 0)
            {
                //什么都不用做
                return data.Clone() as T[];
            }
            int cnt = data.Count();
            T[] data_out = new T[cnt];


            for (int i = 0; i < cnt; i++)
            {
                int idx = i - move;
                if (idx >= cnt)
                    idx -= cnt;
                else if (idx < 0)
                    idx += cnt;

                data_out[i] = data[idx];

            }
            return data_out;

        }
        /// <summary>
        /// 计算极差
        /// </summary>
        /// <param name="data"></param>
        public static int CalMaxMin(int[] data)
        {
            int max = Misc.MyMath.Max(data);
            int min = Misc.MyMath.Min(data);
            if (Misc.MyBase.ISVALIDATA(max))
            {
                return max - min;
            }
            return 0;
        }

        public static double CalMaxMin(double[] data)
        {
            double max = data.Max();
            double min = data.Min();
            if (!double.IsNaN(max))
            {
                return max - min;
            }
            return 0;
        }
        /// <summary>
        /// X轴反向
        /// </summary>
        /// <param name="data"></param>
        /// <param name="mid">中心位置</param>
        /// <returns></returns>
        public static int[] ReverseX(int[] data, int mid)
        {
            //放大
            int[] _diff = new int[data.Count()];
            for (int i = 0; i < data.Count(); i++)
            {
                int idx = mid * 2 - i;
                if (idx >= data.Count())
                    idx -= data.Count();
                else if(idx<0)
                    idx+= data.Count();
                _diff[i] = data[idx];
            }
            return _diff;
        }
        public static T[] ReverseX<T>(T[] data, int mid)
        {
            //放大
            var _diff = new T[data.Count()];
            for (int i = 0; i < data.Count(); i++)
            {
                int idx = mid * 2 - i;
                if (idx >= data.Count())
                    idx -= data.Count();
                else if (idx < 0)
                    idx += data.Count();
                _diff[i] = data[idx];
            }
            return _diff;
        }
        /// <summary>
        /// X轴放大
        /// </summary>
        /// <param name="data"></param>
        /// <param name="mid">中心位置</param>
        /// <param name="z"></param>
        /// <returns></returns>
        public static int[] ZoomX(int[] data, int mid, double z)
        {
            if ( Math.Abs(z - 1)<0.001 )
            {
                return data.Clone() as int[];
            }
            //放大
            int[] _diff = new int[data.Count()];
            for (int i = 0; i < data.Count(); i++)
            {
                double new_offset = i - (mid);
                if (Math.Abs(new_offset) > data.Count() / 2)
                {
                    if (new_offset > 0)
                        new_offset -= data.Count();
                    else
                        new_offset += data.Count();
                }
                double old_offset = new_offset * 1 / z;
                if (Math.Abs(old_offset) > data.Count() / 2)
                {
                    //没数据了
                    _diff[i] = Misc.MyBase.NULL_VALUE;
                }
                else
                {
                    int d1 = (int)Math.Ceiling(old_offset);
                    int d2 = (int)Math.Floor(old_offset);
                    double p1 = old_offset - d2;
                    double p2 = d1 - old_offset;

                    d1 += (mid);
                    if (d1 >= data.Count())
                        d1 -= data.Count();
                    else if (d1 < 0)
                        d1 += data.Count();

                    d2 += (mid);
                    if (d2 >= data.Count())
                        d2 -= data.Count();
                    else if (d2 < 0)
                        d2 += data.Count();

                    if (d1 == d2)
                    {
                        _diff[i] = data[d1];
                    }
                    else
                    {
                        if (Misc.MyBase.ISVALIDATA(data[d1]) && Misc.MyBase.ISVALIDATA(data[d2]))
                            _diff[i] = (int)(data[d1] * p1 + data[d2] * p2);
                        else if (Misc.MyBase.ISVALIDATA(data[d1]))
                            _diff[i] = data[d1];
                        else
                            _diff[i] = data[d2];
                    }
                }
            }
            return _diff;
        }

        /// <summary>
        /// X轴放大
        /// </summary>
        /// <param name="data"></param>
        /// <param name="mid">中心位置</param>
        /// <param name="z"></param>
        /// <returns></returns>
        public static double[] ZoomX(double[] data, int mid, double z)
        {
            //放大
            double[] _diff = new double[data.Count()];
            for (int i = 0; i < data.Count(); i++)
            {
                double new_offset = i - (mid);
                if (Math.Abs(new_offset) > data.Count() / 2)
                {
                    if (new_offset > 0)
                        new_offset -= data.Count();
                    else
                        new_offset += data.Count();
                }
                double old_offset = new_offset * 1 / z;
                if (Math.Abs(old_offset) > data.Count() / 2)
                {
                    //没数据了
                    _diff[i] = double.NaN;
                }
                else
                {
                    int d1 = (int)Math.Ceiling(old_offset);
                    int d2 = (int)Math.Floor(old_offset);
                    double p1 = old_offset - d2;
                    double p2 = d1 - old_offset;

                    d1 += (mid);
                    if (d1 >= data.Count())
                        d1 -= data.Count();
                    else if (d1 < 0)
                        d1 += data.Count();

                    d2 += (mid);
                    if (d2 >= data.Count())
                        d2 -= data.Count();
                    else if (d2 < 0)
                        d2 += data.Count();

                    if (d1 == d2)
                    {
                        _diff[i] = data[d1];
                    }
                    else
                    {

                        if ((!double.IsNaN(data[d1])) && (!double.IsNaN(data[d2])))
                            _diff[i] = data[d1] * p1 + data[d2] * p2;
                        else if (!double.IsNaN(data[d1]))
                            _diff[i] = data[d1];
                        else if (!double.IsNaN(data[d2]))
                            _diff[i] = data[d2];
                        else
                            _diff[i] = double.NaN;
                    }
                }
            }
            return _diff;
        }
        public static double BreakUp(int[] data)
        {
            int avg = Misc.MyMath.Avg(data);
            Dictionary<Range, bool> block = new Dictionary<Range, bool>();
            Range range = new Range();
            bool isBigger = false;
            for (int i = 0; i < data.Count(); i++)
            {
                int idx = i;

                if (range.IsValid)
                {
                    if (data[idx] == avg)
                    {
                        //切换点
                        block.Add(range, isBigger);
                        range = new Range();
                    }
                    else if ((data[idx] > avg))
                    {
                        if (isBigger)
                            range.End = idx;
                        else
                        {
                            //切换点
                            block.Add(range, isBigger);
                            range = new Range() { Begin = idx, End = idx };
                            isBigger = true;
                        }
                    }
                    else
                    {
                        if (!isBigger)
                            range.End = idx;
                        else
                        {
                            //切换点
                            block.Add(range, isBigger);
                            range = new Range() { Begin = idx, End = idx };
                            isBigger = false;
                        }
                    }
                }
                else
                {
                    if (data[idx] == avg)
                    {

                    }
                    else if ((data[idx] > avg))
                    {
                        range = new Range() { Begin = idx, End = idx };
                        isBigger = true;
                    }
                    else
                    {
                        range = new Range() { Begin = idx, End = idx };
                        isBigger = false;
                    }
                }
            }

            Range f = block.Keys.First();
            bool fb = block[f];
            Range l = block.Keys.Last();
            bool lb = block[l];

            if (fb == lb)
            {
                //可能一起的
                if ((f.Begin == 0) && (l.End == data.Count() - 1))
                {
                    //同一块
                    f.End += l.Width;
                    block.Remove(l);
                }
            }

            double block_width_max = block.Keys.Max((r) => { return r.Width; });
            return block_width_max / data.Count();
        }

        public static Range[] Break(int[] data)
        {
            int avg = Misc.MyMath.Avg(data);
            Dictionary<Range, bool> block = new Dictionary<Range, bool>();
            Range range = new Range();
            bool isBigger = false;
            for (int i = 0; i < data.Count(); i++)
            {
                int idx = i;

                if (range.IsValid)
                {
                    if (data[idx] == avg)
                    {
                        //切换点
                        block.Add(range, isBigger);
                        range = new Range();
                    }
                    else if ((data[idx] > avg))
                    {
                        if (isBigger)
                            range.End = idx;
                        else
                        {
                            //切换点
                            block.Add(range, isBigger);
                            range = new Range() { Begin = idx, End = idx };
                            isBigger = true;
                        }
                    }
                    else
                    {
                        if (!isBigger)
                            range.End = idx;
                        else
                        {
                            //切换点
                            block.Add(range, isBigger);
                            range = new Range() { Begin = idx, End = idx };
                            isBigger = false;
                        }
                    }
                }
                else
                {
                    if (data[idx] == avg)
                    {

                    }
                    else if ((data[idx] > avg))
                    {
                        range = new Range() { Begin = idx, End = idx };
                        isBigger = true;
                    }
                    else
                    {
                        range = new Range() { Begin = idx, End = idx };
                        isBigger = false;
                    }
                }
            }

            if (block.Count() == 0)
            {
                return null;
            }
            else if (block.Count() > 1)
            {
                Range f = block.Keys.First();
                bool fb = block[f];
                Range l = block.Keys.Last();
                bool lb = block[l];

                if (fb == lb)
                {
                    //可能一起的
                    if ((f.Begin == 0) && (l.End == data.Count() - 1))
                    {
                        //同一块
                        //f.Begin变为负数
                        f.Begin = f.Begin - l.Width;
                        block.Remove(l);
                    }
                }
            }

            return block.Keys.ToArray();
        }


        /// <summary>
        /// 对横向数据 分区移位（非环型数据）,无效数据使用边上的数据填充;
        /// map 必须是从小到大排列
        /// </summary>
        /// <param name="data">原始数据</param>
        /// <param name="map">key=old_idx, value=new_idx</param>
        /// <returns></returns>
        public static double[] MapX(IEnumerable<double> data, Dictionary<int, int> map)
        {
            if (map == null || map.Count() == 0)
                return data.ToArray();
            double[] data_new = new double[data.Count()];
            if (map.Count() == 1)
            {
                //只是平移而已
                int old_idx0 = map.Keys.ElementAt(0);
                int new_idx0 = map[old_idx0];

                for (int i = 0; i < data.Count(); i++)
                {
                    int new_idx = i;
                    int old_idx = old_idx0 - new_idx0 + new_idx;
                    if (old_idx >= data.Count())
                        old_idx = data.Count() - 1;
                    else if (old_idx < 0)
                        old_idx = 0;
                    data_new[new_idx] = data.ElementAt(old_idx);
                }
                return data_new;
            }

            for (int i = 0; i < map.Count(); i++)
            {
                //第0组
                int old_idx0 = map.Keys.ElementAt(i);
                int new_idx0 = map[old_idx0];

                if (i == 0)
                {
                    MapX(data, data_new, 0, 0, old_idx0, new_idx0);
                }
                else if(i== map.Count()-1)
                { 
                    MapX(data, data_new, old_idx0, new_idx0, data.Count()-1, data.Count() - 1);
                }
                else
                {
                    //第1组
                    int old_idx1 = map.Keys.ElementAt(i+1);
                    int new_idx1 = map[old_idx1];

                    MapX(data, data_new, old_idx0, new_idx0, old_idx1, new_idx1);
                }
            }
            return data_new;
        }

        /// <summary>
        /// 把 data_old 指定2个点的范围，map到data_new;
        /// idx0 必须 比 idx1 小
        /// </summary>
        /// <param name="old_data"></param>
        /// <param name="new_data"></param>
        /// <param name="old_idx0"></param>
        /// <param name="new_idx0"></param>
        /// <param name="old_idx1"></param>
        /// <param name="new_idx1"></param>
        static void MapX(IEnumerable<double> old_data, double[] new_data, int old_idx0, int new_idx0, int old_idx1, int new_idx1) 
        {

            int new_cnt = new_idx1 - new_idx0;
            if (new_cnt < 0)
                throw new Exception("异常, new_idx1 小于 new_idx0");


            int old_cnt = old_idx1 - old_idx0;
            if (old_cnt < 0)
                throw new Exception("异常, new_idx1 小于 new_idx0");


            new_data[new_idx0] = old_data.ElementAt(old_idx0);
            new_data[new_idx1] = old_data.ElementAt(old_idx1);

            //全部数据 小于2个，上面的操作已经完成
            if (new_cnt <=1)
                return;

            double w = 1.0 * old_cnt / new_cnt;
            for (int j = 0; j < new_cnt-1; j++)
            {
                int new_idx = j + new_idx0 + 1;

                double old_idx = j * w + old_idx0;
                int o1 = (int)Math.Ceiling(old_idx);
                int o0 = (int)old_idx;

                if (o0 == o1)
                {
                    int old_idx_0 = o0;
                    new_data[new_idx] = old_data.ElementAt(old_idx_0);
                }
                else
                {
                    //通过权重算值

                    int old_idx_0 = o0;
                    int old_idx_1 = o1;

                    if (!double.IsNaN(old_data.ElementAt(old_idx_1)) && !double.IsNaN(old_data.ElementAt(old_idx_0)))
                    {
                        new_data[new_idx] = old_data.ElementAt(old_idx_1) * (old_idx - o0) + old_data.ElementAt(old_idx_0) * (o1 - old_idx);
                    }
                    else if (!double.IsNaN(old_data.ElementAt(old_idx_0)))
                    {
                        new_data[new_idx] = old_data.ElementAt(old_idx_0);
                    }
                    else if (!double.IsNaN(old_data.ElementAt(old_idx_1)))
                    {
                        new_data[new_idx] = old_data.ElementAt(old_idx_1);
                    }
                    else
                    {
                        new_data[new_idx] = double.NaN;
                    }
                }
            }
        }
        #endregion
    }
}
