void Vector_getMinimumAndX (Vector me, double xmin, double xmax, long channel, int interpolation, double *return_minimum, double *return_xOfMinimum) { long imin, imax, n = my nx; Melder_assert (channel >= 1 && channel <= my ny); double *y = my z [channel]; double minimum, x; if (xmax <= xmin) { xmin = my xmin; xmax = my xmax; } if (! Sampled_getWindowSamples (me, xmin, xmax, & imin, & imax)) { /* * No samples between xmin and xmax. * Try to return the lesser of the values at these two points. */ double yleft = Vector_getValueAtX (me, xmin, channel, interpolation > Vector_VALUE_INTERPOLATION_NEAREST ? Vector_VALUE_INTERPOLATION_LINEAR : Vector_VALUE_INTERPOLATION_NEAREST); double yright = Vector_getValueAtX (me, xmax, channel, interpolation > Vector_VALUE_INTERPOLATION_NEAREST ? Vector_VALUE_INTERPOLATION_LINEAR : Vector_VALUE_INTERPOLATION_NEAREST); minimum = yleft < yright ? yleft : yright; x = yleft == yright ? (xmin + xmax) / 2 : yleft < yright ? xmin : xmax; } else { minimum = y [imin], x = imin; if (y [imax] < minimum) minimum = y [imax], x = imax; if (imin == 1) imin ++; if (imax == my nx) imax --; for (long i = imin; i <= imax; i ++) { if (y [i] < y [i - 1] && y [i] <= y [i + 1]) { double i_real, localMinimum = NUMimproveMinimum (y, n, i, interpolation, & i_real); if (localMinimum < minimum) minimum = localMinimum, x = i_real; } } x = my x1 + (x - 1) * my dx; /* Convert sample to x. */ if (x < xmin) x = xmin; else if (x > xmax) x = xmax; } if (return_minimum) *return_minimum = minimum; if (return_xOfMinimum) *return_xOfMinimum = x; }
void Sampled_getMinimumAndX (Sampled me, double xmin, double xmax, long ilevel, int unit, int interpolate, double *return_minimum, double *return_xOfMinimum) { long imin, imax, i; double minimum = 1e301, xOfMinimum = 0.0; if (xmin == NUMundefined || xmax == NUMundefined) { minimum = xOfMinimum = NUMundefined; goto end; } Function_unidirectionalAutowindow (me, & xmin, & xmax); if (! Function_intersectRangeWithDomain (me, & xmin, & xmax)) { minimum = xOfMinimum = NUMundefined; // requested range and logical domain do not intersect goto end; } if (! Sampled_getWindowSamples (me, xmin, xmax, & imin, & imax)) { /* * No sample centres between xmin and xmax. * Try to return the lesser of the values at these two points. */ double fleft = Sampled_getValueAtX (me, xmin, ilevel, unit, interpolate); double fright = Sampled_getValueAtX (me, xmax, ilevel, unit, interpolate); if (NUMdefined (fleft) && fleft < minimum) minimum = fleft, xOfMinimum = xmin; if (NUMdefined (fright) && fright < minimum) minimum = fright, xOfMinimum = xmax; } else { for (i = imin; i <= imax; i ++) { double fmid = my v_getValueAtSample (i, ilevel, unit); if (fmid == NUMundefined) continue; if (interpolate == FALSE) { if (fmid < minimum) minimum = fmid, xOfMinimum = i; } else { /* * Try an interpolation, possibly even taking into account a sample just outside the selection. */ double fleft = i <= 1 ? NUMundefined : my v_getValueAtSample (i - 1, ilevel, unit); double fright = i >= my nx ? NUMundefined : my v_getValueAtSample (i + 1, ilevel, unit); if (fleft == NUMundefined || fright == NUMundefined) { if (fmid < minimum) minimum = fmid, xOfMinimum = i; } else if (fmid < fleft && fmid <= fright) { double y [4], i_real, localMinimum; y [1] = fleft, y [2] = fmid, y [3] = fright; localMinimum = NUMimproveMinimum (y, 3, 2, NUM_PEAK_INTERPOLATE_PARABOLIC, & i_real); if (localMinimum < minimum) minimum = localMinimum, xOfMinimum = i_real + i - 2; } } } xOfMinimum = my x1 + (xOfMinimum - 1) * my dx; /* From index plus phase to time. */ /* Check boundary values. */ if (interpolate) { double fleft = Sampled_getValueAtX (me, xmin, ilevel, unit, TRUE); double fright = Sampled_getValueAtX (me, xmax, ilevel, unit, TRUE); if (NUMdefined (fleft) && fleft < minimum) minimum = fleft, xOfMinimum = xmin; if (NUMdefined (fright) && fright < minimum) minimum = fright, xOfMinimum = xmax; } if (xOfMinimum < xmin) xOfMinimum = xmin; if (xOfMinimum > xmax) xOfMinimum = xmax; } if (minimum == 1e301) minimum = xOfMinimum = NUMundefined; end: if (return_minimum) *return_minimum = minimum; if (return_xOfMinimum) *return_xOfMinimum = xOfMinimum; }