using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using U.ListOperations.ListSort;

namespace U.ListOperations.UStats
{
    public class Descriptive
    {
        /*
        // Normalize
        public static List<double> getNormalized(List<int> list) { double m = getMean(list); double std = getStandardDeviation(list); List<double> n = new List<double>(); for (int i = 0; i < list.Count; i++) { n.Add((list[i] - m) / std); } return n; }
        public static List<double> getNormalized(List<double> list) { double m = getMean(list); double std = getStandardDeviation(list); List<double> n = new List<double>(); for (int i = 0; i < list.Count; i++) { n.Add((list[i] - m) / std); } return n; }
        public static List<double> getNormalized(List<long> list) { double m = getMean(list); double std = getStandardDeviation(list); List<double> n = new List<double>(); for (int i = 0; i < list.Count; i++) { n.Add((list[i] - m) / std); } return n; }

        // Min
        public static int getMin(List<int> list) { int m = int.MaxValue; foreach (int v in list) { if (v < m) { m = v; } } return m; }
        public static double getMin(List<double> list) { double m = double.MaxValue; foreach (double v in list) { if (v < m) { m = v; } } return m; }
        public static long getMin(List<long> list) { long m = long.MaxValue; foreach (long v in list) { if (v < m) { m = v; } } return m; }
        public static int getMin(List<List<int>> table) { int m = int.MaxValue; foreach (List<int> l in table) { int v = getMin(l); if (v < m) { m = v; } } return m; }
        public static double getMin(List<List<double>> table) { double m = double.MaxValue; foreach (List<double> l in table) { double v = getMin(l); if (v < m) { m = v; } } return m; }
        public static long getMin(List<List<long>> table) { long m = long.MaxValue; foreach (List<long> l in table) { long v = getMin(l); if (v < m) { m = v; } } return m; }
        // Max
        public static int getMax(List<int> list) { int m = int.MinValue; foreach (int v in list) { if (v > m) { m = v; } } return m; }
        public static double getMax(List<double> list) { double m = double.MinValue; foreach (double v in list) { if (v > m) { m = v; } } return m; }
        public static long getMax(List<long> list) { long m = long.MinValue; foreach (long v in list) { if (v > m) { m = v; } } return m; }
        public static int getMax(List<List<int>> table) { int m = int.MinValue; foreach (List<int> l in table) { int v = getMax(l); if (v > m) { m = v; } } return m; }
        public static double getMax(List<List<double>> table) { double m = double.MinValue; foreach (List<double> l in table) { double v = getMax(l); if (v > m) { m = v; } } return m; }
        public static long getMax(List<List<long>> table) { long m = long.MinValue; foreach (List<long> l in table) { long v = getMax(l); if (v > m) { m = v; } } return m; }
        
        // Sum
        public static int getSum(List<int> list) { if (list == null) { return 0; } int sum = 0; for (int i = 0; i < list.Count; i++) { sum += list[i]; } return sum; }
        public static double getSum(List<double> list) { if (list == null) { return 0; } double sum = 0; for (int i = 0; i < list.Count; i++) { sum += list[i]; } return sum; }
        public static long getSum(List<long> list) { if (list == null) { return 0; } long sum = 0; for (int i = 0; i < list.Count; i++) { sum += list[i]; } return sum; }
        // Mean
        public static double getMean(List<int> list) { return Convert.ToDouble(getSum(list)) / list.Count; }
        public static double getMean(List<double> list) { return Convert.ToDouble(getSum(list)) / list.Count; }
        public static double getMean(List<long> list) { return Convert.ToDouble(getSum(list)) / list.Count; }
        // Squared Errors
        public static double getSumSquaredErrors(List<int> list) { double mean = getMean(list); return getSumSquaredErrors(list, mean); }
        public static double getSumSquaredErrors(List<int> list, double mean) { if (list == null) { return 0.0; } double sum = 0.0; for (int i = 0; i < list.Count; i++) { sum += Math.Pow(list[i] - mean, 2.0); } return sum; }
        public static double getSumSquaredErrors(List<double> list) { double mean = getMean(list); return getSumSquaredErrors(list, mean); }
        public static double getSumSquaredErrors(List<double> list, double mean) { if (list == null) { return 0.0; } double sum = 0.0; for (int i = 0; i < list.Count; i++) { sum += Math.Pow(list[i] - mean, 2.0); } return sum; }
        public static double getSumSquaredErrors(List<long> list) { double mean = getMean(list); return getSumSquaredErrors(list, mean); }
        public static double getSumSquaredErrors(List<long> list, double mean) { if (list == null) { return 0.0; } double sum = 0.0; for (int i = 0; i < list.Count; i++) { sum += Math.Pow(list[i] - mean, 2.0); } return sum; }
        // Variance
        public static double getVariance(List<int> list, double mean) { if (list == null) { return 0.0; } return getSumSquaredErrors(list, mean) / (list.Count - 1.0); }
        public static double getVariance(List<int> list) { return getVariance(list, getMean(list)); }
        public static double getVariance(List<double> list, double mean) { if (list == null) { return 0.0; } return getSumSquaredErrors(list, mean) / (list.Count - 1.0); }
        public static double getVariance(List<double> list) { return getVariance(list, getMean(list)); }
        public static double getVariance(List<long> list, double mean) { if (list == null) { return 0.0; } return getSumSquaredErrors(list, mean) / (list.Count - 1.0); }
        public static double getVariance(List<long> list) { return getVariance(list, getMean(list)); }
        // Standard Deviation
        public static double getStandardDeviation(List<int> list) { return Math.Sqrt(getVariance(list)); }
        public static double getStandardDeviation(List<int> list, double mean) { return Math.Sqrt(getVariance(list, mean)); }
        public static double getStandardDeviation(List<double> list) { return Math.Sqrt(getVariance(list)); }
        public static double getStandardDeviation(List<double> list, double mean) { return Math.Sqrt(getVariance(list, mean)); }
        public static double getStandardDeviation(List<long> list) { return Math.Sqrt(getVariance(list)); }
        public static double getStandardDeviation(List<long> list, double mean) { return Math.Sqrt(getVariance(list, mean)); }
        // Spearman
        public static List<double> getSpearmanRanks(List<int> list, bool ascending) { SortList sortList = new SortList(list); return sortList.calcGetSpearmanRanks(ascending); }
        public static List<double> getSpearmanRanks(List<double> list, bool ascending) { SortList sortList = new SortList(list); return sortList.calcGetSpearmanRanks(ascending); }
        public static List<double> getSpearmanRanks(List<long> list, bool ascending) { SortList sortList = new SortList(list); return sortList.calcGetSpearmanRanks(ascending); }
        // Signal-to-Noise Ratio
        public static double getSignalToNoiseRatio(List<int> list) { double m = getMean(list); return m / getStandardDeviation(list, m); }
        public static double getSignalToNoiseRatio(List<double> list) { double m = getMean(list); return m / getStandardDeviation(list, m); }
        public static double getSignalToNoiseRatio(List<long> list) { double m = getMean(list); return m / getStandardDeviation(list, m); }
        public static double getSignalToNoiseRatio(List<int> list, int sizeOfClass1) { if (sizeOfClass1 > list.Count - 1 || sizeOfClass1 < 1) { return -100.0; } List<int> l1 = UList.getFirstItems(list, sizeOfClass1); List<int> l2 = UList.getLastItems(list, list.Count - sizeOfClass1); double m1 = getMean(l1); double m2 = getMean(l2); double std1 = getStandardDeviation(l1, m1); double std2 = getStandardDeviation(l2, m2); return (m1 - m2) / (std1 + std2); }
        public static double getSignalToNoiseRatio(List<double> list, int sizeOfClass1) { if (sizeOfClass1 > list.Count - 1 || sizeOfClass1 < 1) { return -100.0; } List<double> l1 = UList.getFirstItems(list, sizeOfClass1); List<double> l2 = UList.getLastItems(list, list.Count - sizeOfClass1); double m1 = getMean(l1); double m2 = getMean(l2); double std1 = getStandardDeviation(l1, m1); double std2 = getStandardDeviation(l2, m2); return (m1 - m2) / (std1 + std2); }
        public static double getSignalToNoiseRatio(List<long> list, int sizeOfClass1) { if (sizeOfClass1 > list.Count - 1 || sizeOfClass1 < 1) { return -100.0; } List<long> l1 = UList.getFirstItems(list, sizeOfClass1); List<long> l2 = UList.getLastItems(list, list.Count - sizeOfClass1); double m1 = getMean(l1); double m2 = getMean(l2); double std1 = getStandardDeviation(l1, m1); double std2 = getStandardDeviation(l2, m2); return (m1 - m2) / (std1 + std2); }

        //*/
    }
}
