public void TestSingleDatapointAsTwoInLinearDoubleInterpolable() { LinearDoubleInterpolator ldi = new LinearDoubleInterpolator(); ldi.SetData(new double[] { 1.0, 1.1 }, new double[] { 5.0, 5.0 }); double five_point_zero = ldi.GetYValue(123.0); Assert.IsTrue(five_point_zero == 5.0); }
/// <summary> /// Gets the percentile for item. Note: with [0,1,2,3,3,3], 3 will be in the 50th percentile. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="srcItems">The _SRC items.</param> /// <param name="targetItem">The target item.</param> /// <param name="valueGetter">The value getter.</param> /// <param name="pd">The object that will hold state for repeated calls to this method on the same list.</param> /// <returns></returns> public static double GetPercentileForItem <T>(this List <T> srcItems, T targetItem, Func <T, double> valueGetter, ref object pd) { if (pd == null) { List <T> lclSrcItems = new List <T>(srcItems); lclSrcItems.Sort((t1, t2) => Comparer <double> .Default.Compare(valueGetter(t1), valueGetter(t2))); int nItems = lclSrcItems.Count; // Added the following to collapse repeated xvalues (with which it is impossible // to calculate a slope, dy/dx because dx==0). List <double> data = new List <double>(); List <double> percentiles = new List <double>(); for (int i = 0; i < nItems; i++) { double xval = valueGetter(lclSrcItems[i]); if (data.Count == 0 || xval != data.Last()) { data.Add(xval); percentiles.Add(((double)i + 1) / nItems); } } // The preceding was added. //double[] data = new double[nItems]; //double[] percentiles = new double[nItems]; //for (int i = 0; i < nItems; i++) { // data[i] = valueGetter(srcItems[i]); // percentiles[i] = ((double)i+1) / ((double)nItems); //} LinearDoubleInterpolator ldi = new LinearDoubleInterpolator(); //ldi.SetData(data, percentiles); //_pd = new PercentileData() { min = data[0], ldi = ldi }; ldi.SetData(data.ToArray(), percentiles.ToArray()); pd = new PercentileData() { Min = data[0], Ldi = ldi }; } PercentileData lclPd = (PercentileData)pd; return(Math.Max(0, Math.Min(1, lclPd.Ldi.GetYValue(valueGetter(targetItem))))); }