} //# end of higher.local.max //# new_0.11 private double[] SplitStartingValuesLeftRight(GenObject o, double target, SGNFnAParam A, double[] range, double[] startValues) { double[] start = new double[2] { Tools.NA, Tools.NA }; double[] lsStart = startValues.Where(number => (number < A.Mode) && (number > range[0])).ToArray(); double[] rsStart = startValues.Where(number => (number > A.Mode) && (number < range[1])).ToArray(); if (lsStart.Length == 1) { start[0] = lsStart[0]; } else if (lsStart.Length > 1) { double[] f = new double[lsStart.Length]; for (int i = 0; i < lsStart.Length; i++) { f[i] = o.LogF(lsStart[i], A); } double[] d = f.Substract(target).Abs(); int w = d.WhichMin(); start[0] = lsStart[w]; } if (rsStart.Length == 1) { start[1] = rsStart[0]; } else if (rsStart.Length > 1) { double[] f = new double[rsStart.Length]; for (int i = 0; i < rsStart.Length; i++) { f[i] = o.LogF(rsStart[i], A); } double[] d = f.Substract(target).Abs(); int w = d.WhichMin(); start[1] = rsStart[w]; } return(start); } //# end of split.starting.values.leftRight
private double HigherLocalMax(GenObject o, SGNFnAParam A, double dipX, double[] range, double epsilon) { //# Find a starting point on each side of dip.x double[] start = o.Start(A); double tmp = start.Substract(dipX).Abs().Max(); double startLeft = start.Min(); if (startLeft > dipX) { startLeft = dipX - tmp; } double startRight = start.Max(); if (startRight < dipX) { startRight = dipX + tmp; } //# Look for starting points with negative values for h'' //# i) on left side bool cntn = o.LogFSecond(startLeft, A) > 0; while (cntn) { startLeft = startLeft - tmp; if (startLeft < range[0]) { startLeft = (range[0] + startLeft + tmp) / 2; } cntn = o.LogFSecond(startLeft, A) > 0; } //# ii) on right side cntn = o.LogFSecond(startRight, A) > 0; while (cntn) { startRight = startRight + tmp; cntn = o.LogFSecond(startRight, A) > 0; } //# Run pure Newton-Raphson to find local max on each side //# i) left side double x = startLeft; cntn = true; double hp = o.LogFPrime(x, A); while (cntn) { double change = hp / o.LogFSecond(x, A); x = x - change; hp = o.LogFPrime(x, A); cntn = Math.Abs(hp) > epsilon; } double localModeLeft = x; //# ii) right-side x = startRight; cntn = true; hp = o.LogFPrime(x, A); while (cntn) { double change = hp / o.LogFSecond(x, A); x = x - change; hp = o.LogFPrime(x, A); cntn = Math.Abs(hp) > epsilon; } double localModeRight = x; double hLeft = o.LogF(localModeLeft, A); double hRight = o.LogF(localModeRight, A); x = hLeft > hRight ? localModeLeft : localModeRight; return(x); } //# end of higher.local.max
} //# end of split.starting.values.leftRight //# new_0.11 private MaxFastTrackObject MaxFastTrack(GenObject o, SGNFnAParam A, double lowerLimit, double rightsideX, double rightsideHp, double epsilon = 1e-4, double epsilonX = 1e-20) { double x = rightsideX; double h = o.LogF(x, A); double hp = rightsideHp; //b = list(x = c(NA, x), h = c(NA, h), hp = c(NA, hp)) double[] bX = new double[2] { x, Tools.NA }; double[] bH = new double[2] { h, Tools.NA }; double[] bHp = new double[2] { hp, Tools.NA }; x = (x + lowerLimit) / 2; bool cntn = true; //# Find a point with positive slope (that is, to the left of the mode) while (cntn) { hp = o.LogFPrime(x, A); if (hp > 0) { cntn = double.IsInfinity(hp); if (cntn) { double nextX = (3 * x - lowerLimit) / 2.0; lowerLimit = x; cntn = Math.Abs(nextX - x) > epsilonX; if (cntn) { x = nextX; } } } else { x = (x + lowerLimit) / 2.0; } } hp = o.LogFPrime(x, A); bool converged = Tools.IsFinite(hp) & (hp > 0); cntn = converged; while (cntn) { int side = hp > 0 ? 0 : 1; bX[side] = x; bH[side] = o.LogF(x, A); bHp[side] = hp; double bDiff = bHp.Diff()[0]; if (bDiff == 0) { x = bX.Mean(); } else { x = (bHp.Multiply(bX).Diff()[0] - bH.Diff()[0]) / bDiff; if ((x <= bX[0]) || (x >= bX[1])) { x = bX.Mean(); } hp = o.LogFPrime(x, A); cntn = Math.Abs(hp) > epsilon; } } h = o.LogF(x, A); return(new MaxFastTrackObject(x, h, converged)); } //# end of max.fastTrack