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

namespace DiscreteChoiceModel.MDMHelpers
{
    class LambdaBounds
    {
        // Sta
        public static double[] getAddSta(double lbV, double ubV, double[] cdfInv0, double[] cdfInv1)
        {
            double[] range = new double[2];
            range[0] = double.MaxValue;
            range[1] = double.MinValue;
            for (int k = 0; k < cdfInv0.Length; k++)
            {
                //range[0] = Math.Max(range[0], lbV + cdfInv0[k]);
                //range[1] = Math.Min(range[1], ubV + cdfInv1[k]);
                range[0] = Math.Min(range[0], cdfInv0[k]);
                range[1] = Math.Max(range[1], cdfInv1[k]);
            }
            range[0] += lbV;
            range[1] += ubV;
            return range;
        }
        public static double[] getMulSta(double lbV, double ubV, double[] cdfInv0, double[] cdfInv1)
        {
            double[] range = new double[2];
            range[0] = double.MaxValue;
            range[1] = double.MinValue;
            for (int k = 0; k < cdfInv0.Length; k++)
            {
                range[0] = Math.Min(range[0], cdfInv0[k]);
                range[1] = Math.Max(range[1], cdfInv1[k]);
            }
            range[0] *= lbV;
            range[1] *= ubV;
            return range;
        }

        
        
        // Dyn
        public static double[] getAddDyn(double[] V, double[] cdfInv0, double[] cdfInv1)
        {
            double[] range = new double[2];
            range[0] = double.MaxValue;
            range[1] = double.MinValue;
            for (int k = 0; k < V.Length; k++)
            {
                range[0] = Math.Min(range[0], V[k] + cdfInv0[k]);
                range[1] = Math.Max(range[1], V[k] + cdfInv1[k]);
            }
            return range;
        }
        public static double[] getMulDyn(double[] V, double[] cdfInv0, double[] cdfInv1)
        {
            double[] range = new double[2];
            range[0] = double.MaxValue;
            range[1] = double.MinValue;
            for (int k = 0; k < V.Length; k++)
            {
                range[0] = Math.Min(range[0], V[k] * cdfInv0[k]);
                range[1] = Math.Max(range[1], V[k] * cdfInv1[k]);
            }
            return range;
        }


        /*/ Dyn-Prev
        public static double[] getAddDynPrev(double[] V, double[] lbFinv, double[] ubFinv, double[] prevV, double prevLambda)
        {
            if (prevV == null) { return getAddDyn(V, lbFinv, ubFinv); }
            double[] range = new double[2];
            range[0] = double.MinValue;
            range[1] = double.MaxValue;
            for (int k = 0; k < V.Length; k++)
            {
                range[0] = Math.Max(range[0], V[k] - prevV[k] + lbFinv[k] - ubFinv[k]);
                range[1] = Math.Min(range[1], V[k] - prevV[k] + ubFinv[k] - lbFinv[k]);
            }
            range[0] = prevLambda + range[0];
            range[1] = prevLambda + range[1];
            return range;
        }
        public static double[] getMulDynPrev(double[] V, double[] lbFinv, double[] ubFinv, double[] prevV, double prevLambda)
        {
            if (prevV == null) { return getMulDyn(V, lbFinv, ubFinv); }
            double[] range = new double[2];
            range[0] = double.MinValue;
            range[1] = double.MaxValue;
            for (int k = 0; k < V.Length; k++)
            {
                range[0] = Math.Max(range[0], (V[k] / prevV[k]) * (lbFinv[k] / ubFinv[k]));
                range[1] = Math.Min(range[1], (V[k] / prevV[k]) * (ubFinv[k] / lbFinv[k]));
            }
            range[0] = prevLambda * range[0];
            range[1] = prevLambda * range[1];
            return range;
        }
        //*/
    }
}
