@@ -65,8 +65,8 @@ function upsample_linear(
6565end
6666
6767# ---------------------------------------------------------------------------
68- # Nearest-neighbour upsampling
69- # (Interpolations.jl Gridded(Constant()) for non-uniform knots )
68+ # Nearest-neighbour upsampling (pure Julia – avoids Interpolations.jl API
69+ # version uncertainty for Gridded(Constant) boundary modes )
7070# ---------------------------------------------------------------------------
7171
7272"""
@@ -81,7 +81,7 @@ function upsample_nearest(
8181):: Vector{T} where {T<: Real }
8282 x = collect (1.0 : Float64 (length (y)))
8383 _, y_new = upsample_nearest (x, y, factor; plot = plot)
84- return y_new
84+ return collect (T, y_new)
8585end
8686
8787function upsample_nearest (
@@ -96,10 +96,8 @@ function upsample_nearest(
9696 n >= 2 || throw (ArgumentError (" Need at least 2 points" ))
9797
9898 xf = float .(x)
99- itp = interpolate ((xf,), float .(y), Gridded (Constant {Nearest} ()))
100- etp = extrapolate (itp, Flat ())
10199 x_new = range (xf[1 ], xf[end ]; length = (n - 1 ) * factor + 1 )
102- y_new = etp .( x_new)
100+ y_new = _nearest (xf, float .(y), x_new)
103101
104102 if plot; _show_upsample_plot (x, y, x_new, y_new, " Nearest" ) end
105103 return collect (float (Tx), x_new), y_new
@@ -113,18 +111,35 @@ function upsample_nearest(
113111) where {Tx<: Real ,Ty<: Real }
114112 length (x) == length (y) || throw (DimensionMismatch (" x and y must have same length" ))
115113
116- xf = float .(x)
117- itp = interpolate ((xf,), float .(y), Gridded (Constant {Nearest} ()))
118- etp = extrapolate (itp, Flat ())
119- y_new = etp .(x_new)
120-
114+ y_new = _nearest (float .(x), float .(y), x_new)
121115 if plot; _show_upsample_plot (x, y, x_new, y_new, " Nearest" ) end
122116 return collect (float (Tx), x_new), y_new
123117end
124118
125119# ---------------------------------------------------------------------------
126- # Internal plot helper
120+ # Internal helpers
127121# ---------------------------------------------------------------------------
122+
123+ function _nearest (
124+ x:: AbstractVector{F} ,
125+ y:: AbstractVector{F} ,
126+ x_new,
127+ ):: Vector{F} where {F<: AbstractFloat }
128+ n = length (x)
129+ result = Vector {F} (undef, length (x_new))
130+ for (k, xk) in enumerate (x_new)
131+ if xk <= x[1 ]; result[k] = y[1 ]; continue end
132+ if xk >= x[n]; result[k] = y[n]; continue end
133+ lo, hi = 1 , n
134+ while hi - lo > 1
135+ mid = (lo + hi) >>> 1
136+ x[mid] <= xk ? lo = mid : hi = mid
137+ end
138+ result[k] = abs (xk - x[lo]) <= abs (xk - x[hi]) ? y[lo] : y[hi]
139+ end
140+ return result
141+ end
142+
128143function _show_upsample_plot (x_orig, y_orig, x_new, y_new, method_name:: String )
129144 buff_mod = Base. moduleroot (parentmodule (Upsample))
130145 plots_mod = getfield (buff_mod, :Plots )
0 commit comments