# HG changeset patch # User Rik # Date 1397012538 25200 # Node ID 4792a115c7358d8f332ef591888daac2da5568b8 # Parent a25bbe8c954cb5bfda6d24aa803da24fd7f848f5 interp2.m: Add input validation for strictly monotonic x,y (bug #41838). * interp2.m: Add input validation for strictly monotonic x,y (bug #41838). Move input validation of x,y out of individual method blocks and into common validation section at start of function. Don't unnecessarily create meshgridded XI, YI for "spline" method. Add %!tests for strictly monotonic inputs. diff -r a25bbe8c954c -r 4792a115c735 scripts/general/interp2.m --- a/scripts/general/interp2.m Tue Apr 08 16:29:29 2014 -0400 +++ b/scripts/general/interp2.m Tue Apr 08 20:02:18 2014 -0700 @@ -140,7 +140,7 @@ print_usage (); endswitch - ## Type checking. + ## Type checking if (! ismatrix (Z)) error ("interp2: Z must be a matrix"); endif @@ -149,6 +149,9 @@ endif if (! ischar (method)) error ("interp2: METHOD must be a string"); + elseif (method(1) == "*") + warning ("interp2: ignoring unsupported '*' flag to METHOD"); + method(1) = []; endif if (isnumeric (extrap) && isscalar (extrap)) ## Typical case @@ -158,11 +161,6 @@ error ('interp2: EXTRAP must be a numeric scalar or "extrap"'); endif - if (method(1) == "*") - warning ("interp2: ignoring unsupported '*' flag to METHOD"); - method(1) = []; - endif - ## Define X, Y, XI, YI if needed [zr, zc] = size (Z); if (isempty (X)) @@ -182,19 +180,32 @@ error ("interp2: XI, YI must be numeric"); endif - if (any (strcmp (method, {"nearest", "linear", "pchip", "cubic"}))) + if (isvector (X) && isvector (Y)) + X = X(:); Y = Y(:); + elseif (size_equal (X, Y)) + X = X(1,:).'; Y = Y(:,1); + else + error ("interp2: X and Y must be matrices of equal size"); + endif + if (columns (Z) != length (X) || rows (Z) != length (Y)) + error ("interp2: X and Y size must match the dimensions of Z"); + endif + dx = diff (X); + if (all (dx < 0)) + X = flipud (X); + Z = fliplr (Z); + elseif (any (dx <= 0)) + error ("interp2: X must be strictly monotonic"); + endif + dy = diff (Y); + if (all (dy < 0)) + Y = flipud (Y); + Z = flipud (Z); + elseif (any (dy <= 0)) + error ("interp2: Y must be strictly monotonic"); + endif - ## If X and Y vectors produce a grid from them - if (isvector (X) && isvector (Y)) - X = X(:); Y = Y(:); - elseif (size_equal (X, Y)) - X = X(1,:)'; Y = Y(:,1); - else - error ("interp2: X and Y must be matrices of equal size"); - endif - if (columns (Z) != length (X) || rows (Z) != length (Y)) - error ("interp2: X and Y size must match the dimensions of Z"); - endif + if (any (strcmp (method, {"nearest", "linear", "pchip", "cubic"}))) ## If Xi and Yi are vectors of different orientation build a grid if ((rows (XI) == 1 && columns (YI) == 1) @@ -336,24 +347,9 @@ else - ## Check dimensions of X and Y - if (isvector (X) && isvector (Y)) - X = X(:).'; - Y = Y(:); - if (! isequal ([length(Y), length(X)], size (Z))) - error ("interp2: X and Y size must match the dimensions of Z"); - endif - elseif (! size_equal (X, Y)) - error ("interp2: X and Y must be matrices of equal size"); - elseif (! size_equal (X, Z)) - error ("interp2: X and Y size must match the dimensions of Z"); - endif - ## Check dimensions of XI and YI if (isvector (XI) && isvector (YI) && ! size_equal (XI, YI)) - XI = XI(:).'; - YI = YI(:); - [XI, YI] = meshgrid (XI, YI); + XI = XI(:).'; YI = YI(:); elseif (! size_equal (XI, YI)) error ("interp2: XI and YI must be matrices of equal size"); endif @@ -420,7 +416,7 @@ if (strcmp (method, "spline")) if (isgriddata (XI) && isgriddata (YI')) - ZI = __splinen__ ({Y(:,1).', X(1,:)}, Z, {YI(:,1), XI(1,:)}, extrap, + ZI = __splinen__ ({Y, X}, Z, {YI(:,1), XI(1,:)}, extrap, "spline"); else error ("interp2: XI, YI must have uniform spacing ('meshgrid' format)"); @@ -634,6 +630,10 @@ %! X = meshgrid (1:4); %! assert (interp2 (X, 2.5, 2.5, "nearest"), 3); +## re-order monotonically decreasing (bug #41838). +%!assert (interp2 ([1 2 3], [3 2 1], magic (3), 2.5, 3), 3.5); +%!assert (interp2 ([3 2 1], [1 2 3], magic (3), 1.5, 1), 3.5); + %!shared z, zout, tol %! z = [1 3 5; 3 5 7; 5 7 9]; %! zout = [1 2 3 4 5; 2 3 4 5 6; 3 4 5 6 7; 4 5 6 7 8; 5 6 7 8 9]; @@ -659,10 +659,10 @@ %!error interp2 (1, -1) %!error interp2 (1, 1.5) %!error interp2 (1, 1, 1, 1, 1, 2) +%!warning interp2 (rand (3,3), 1, "*linear"); %!error interp2 (1, 1, 1, 1, 1, 'linear', {1}) %!error interp2 (1, 1, 1, 1, 1, 'linear', ones (2,2)) %!error interp2 (1, 1, 1, 1, 1, 'linear', "abc") -%!warning interp2 (rand (3,3), 1, "*linear"); %!error interp2 ({1}, 1, 1, 1, 1) %!error interp2 (1, {1}, 1, 1, 1) %!error interp2 (1, 1, 1, {1}, 1) @@ -671,16 +671,12 @@ %!error interp2 (ones(2,2), ones(2,3), 1, 1, 1) %!error interp2 (1:3, 1:3, ones (3,2), 1, 1) %!error interp2 (1:2, 1:2, ones (3,2), 1, 1) +%!error interp2 ([1 0 2], 1:3, ones (3,3), 1, 1) +%!error interp2 (1:3, [1 0 2], ones (3,3), 1, 1) %!error interp2 (1, 1, 1, ones(2,2), 1) %!error interp2 (1, 1, 1, 1, ones(2,2)) %!error interp2 (1, 1, 1, 1, 1, "pchip") %!error interp2 (1, 1, 1, 1, 1, "cubic") -%!error interp2 (1:3, 1:3, ones (3,2), 1, 1, "spline") -%!error interp2 (1:2, 1:2, ones (3,2), 1, 1, "spline") -%!error interp2 (ones(2,2), 1, 1, 1, 1, "spline") -%!error interp2 (ones(2,2), ones(2,3), 1, 1, 1, "spline") -%!error interp2 (1, 1, 1, ones(2,2), 1, "spline") -%!error interp2 (1, 1, 1, 1, ones(2,2), "spline") %!error interp2 (1, 1, 1, [1 2 4], [1 2 3], "spline") %!error interp2 (1, 1, 1, [1 2 3], [1 2 4], "spline") %!error interp2 (1, 1, 1, 1, 1, "foobar")