comparison scripts/general/interp2.m @ 11587:c792872f8942

all script files: untabify and strip trailing whitespace
author John W. Eaton <jwe@octave.org>
date Thu, 20 Jan 2011 17:35:29 -0500
parents 702dbd0c53f5
children b0084095098e
comparison
equal deleted inserted replaced
11586:12df7854fa7c 11587:c792872f8942
25 ## @deftypefnx {Function File} {@var{zi} =} interp2 (@dots{}, @var{method}, @var{extrapval}) 25 ## @deftypefnx {Function File} {@var{zi} =} interp2 (@dots{}, @var{method}, @var{extrapval})
26 ## 26 ##
27 ## Two-dimensional interpolation. @var{x}, @var{y} and @var{z} describe a 27 ## Two-dimensional interpolation. @var{x}, @var{y} and @var{z} describe a
28 ## surface function. If @var{x} and @var{y} are vectors their length 28 ## surface function. If @var{x} and @var{y} are vectors their length
29 ## must correspondent to the size of @var{z}. @var{x} and @var{y} must be 29 ## must correspondent to the size of @var{z}. @var{x} and @var{y} must be
30 ## monotonic. If they are matrices they must have the @code{meshgrid} 30 ## monotonic. If they are matrices they must have the @code{meshgrid}
31 ## format. 31 ## format.
32 ## 32 ##
33 ## @table @code 33 ## @table @code
34 ## @item interp2 (@var{x}, @var{y}, @var{Z}, @var{xi}, @var{yi}, @dots{}) 34 ## @item interp2 (@var{x}, @var{y}, @var{Z}, @var{xi}, @var{yi}, @dots{})
35 ## Returns a matrix corresponding to the points described by the 35 ## Returns a matrix corresponding to the points described by the
36 ## matrices @var{xi}, @var{yi}. 36 ## matrices @var{xi}, @var{yi}.
37 ## 37 ##
38 ## If the last argument is a string, the interpolation method can 38 ## If the last argument is a string, the interpolation method can
39 ## be specified. The method can be 'linear', 'nearest' or 'cubic'. 39 ## be specified. The method can be 'linear', 'nearest' or 'cubic'.
40 ## If it is omitted 'linear' interpolation is assumed. 40 ## If it is omitted 'linear' interpolation is assumed.
41 ## 41 ##
42 ## @item interp2 (@var{z}, @var{xi}, @var{yi}) 42 ## @item interp2 (@var{z}, @var{xi}, @var{yi})
43 ## Assumes @code{@var{x} = 1:rows (@var{z})} and @code{@var{y} = 43 ## Assumes @code{@var{x} = 1:rows (@var{z})} and @code{@var{y} =
44 ## 1:columns (@var{z})} 44 ## 1:columns (@var{z})}
45 ## 45 ##
46 ## @item interp2 (@var{z}, @var{n}) 46 ## @item interp2 (@var{z}, @var{n})
47 ## Interleaves the matrix @var{z} n-times. If @var{n} is omitted a value 47 ## Interleaves the matrix @var{z} n-times. If @var{n} is omitted a value
48 ## of @code{@var{n} = 1} is assumed. 48 ## of @code{@var{n} = 1} is assumed.
49 ## @end table 49 ## @end table
50 ## 50 ##
51 ## The variable @var{method} defines the method to use for the 51 ## The variable @var{method} defines the method to use for the
52 ## interpolation. It can take one of the following values 52 ## interpolation. It can take one of the following values
53 ## 53 ##
54 ## @table @asis 54 ## @table @asis
55 ## @item 'nearest' 55 ## @item 'nearest'
56 ## Return the nearest neighbor. 56 ## Return the nearest neighbor.
57 ## 57 ##
68 ## Cubic spline interpolation--smooth first and second derivatives 68 ## Cubic spline interpolation--smooth first and second derivatives
69 ## throughout the curve. 69 ## throughout the curve.
70 ## @end table 70 ## @end table
71 ## 71 ##
72 ## If a scalar value @var{extrapval} is defined as the final value, then 72 ## If a scalar value @var{extrapval} is defined as the final value, then
73 ## values outside the mesh as set to this value. Note that in this case 73 ## values outside the mesh as set to this value. Note that in this case
74 ## @var{method} must be defined as well. If @var{extrapval} is not 74 ## @var{method} must be defined as well. If @var{extrapval} is not
75 ## defined then NA is assumed. 75 ## defined then NA is assumed.
76 ## 76 ##
77 ## @seealso{interp1} 77 ## @seealso{interp1}
78 ## @end deftypefn 78 ## @end deftypefn
79 79
80 ## Author: Kai Habel <kai.habel@gmx.de> 80 ## Author: Kai Habel <kai.habel@gmx.de>
81 ## 2005-03-02 Thomas Weber <weber@num.uni-sb.de> 81 ## 2005-03-02 Thomas Weber <weber@num.uni-sb.de>
82 ## * Add test cases 82 ## * Add test cases
83 ## 2005-03-02 Paul Kienzle <pkienzle@users.sf.net> 83 ## 2005-03-02 Paul Kienzle <pkienzle@users.sf.net>
84 ## * Simplify 84 ## * Simplify
85 ## 2005-04-23 Dmitri A. Sergatskov <dasergatskov@gmail.com> 85 ## 2005-04-23 Dmitri A. Sergatskov <dasergatskov@gmail.com>
86 ## * Modified demo and test for new gnuplot interface 86 ## * Modified demo and test for new gnuplot interface
123 if (ischar (varargin{4})) 123 if (ischar (varargin{4}))
124 [Z, XI, YI, method, extrapval] = deal (varargin{:}); 124 [Z, XI, YI, method, extrapval] = deal (varargin{:});
125 else 125 else
126 [X, Y, Z, XI, YI] = deal (varargin{:}); 126 [X, Y, Z, XI, YI] = deal (varargin{:});
127 endif 127 endif
128 case 6 128 case 6
129 [X, Y, Z, XI, YI, method] = deal (varargin{:}); 129 [X, Y, Z, XI, YI, method] = deal (varargin{:});
130 case 7 130 case 7
131 [X, Y, Z, XI, YI, method, extrapval] = deal (varargin{:}); 131 [X, Y, Z, XI, YI, method, extrapval] = deal (varargin{:});
132 otherwise 132 otherwise
133 print_usage (); 133 print_usage ();
134 endswitch 134 endswitch
135 135
136 ## Type checking. 136 ## Type checking.
137 if (!ismatrix (Z)) 137 if (!ismatrix (Z))
138 error ("interp2: Z must be a matrix"); 138 error ("interp2: Z must be a matrix");
139 endif 139 endif
140 if (!isempty (n) && !isscalar (n)) 140 if (!isempty (n) && !isscalar (n))
141 error ("interp2: N must be a scalar"); 141 error ("interp2: N must be a scalar");
142 endif 142 endif
143 if (!ischar (method)) 143 if (!ischar (method))
144 error ("interp2: METHOD must be a string"); 144 error ("interp2: METHOD must be a string");
145 endif 145 endif
146 if (ischar (extrapval) || strcmp (extrapval, "extrap")) 146 if (ischar (extrapval) || strcmp (extrapval, "extrap"))
147 extrapval = []; 147 extrapval = [];
148 elseif (!isscalar (extrapval)) 148 elseif (!isscalar (extrapval))
149 error ("interp2: EXTRAPVAL must be a scalar"); 149 error ("interp2: EXTRAPVAL must be a scalar");
150 endif 150 endif
151 151
152 ## Define X, Y, XI, YI if needed 152 ## Define X, Y, XI, YI if needed
153 [zr, zc] = size (Z); 153 [zr, zc] = size (Z);
154 if (isempty (X)) 154 if (isempty (X))
155 X = 1:zc; 155 X = 1:zc;
156 Y = 1:zr; 156 Y = 1:zr;
157 endif 157 endif
158 if (! isnumeric (X) || ! isnumeric (Y)) 158 if (! isnumeric (X) || ! isnumeric (Y))
159 error ("interp2: X, Y must be numeric matrices"); 159 error ("interp2: X, Y must be numeric matrices");
160 endif 160 endif
161 if (! isempty (n)) 161 if (! isempty (n))
162 p = 2^n; 162 p = 2^n;
163 XI = (p:p*zc)/p; 163 XI = (p:p*zc)/p;
164 YI = (p:p*zr)'/p; 164 YI = (p:p*zr)'/p;
165 endif 165 endif
166 if (! isnumeric (XI) || ! isnumeric (YI)) 166 if (! isnumeric (XI) || ! isnumeric (YI))
167 error ("interp2: XI, YI must be numeric"); 167 error ("interp2: XI, YI must be numeric");
168 endif 168 endif
169 169
170 170
171 if (strcmp (method, "linear") || strcmp (method, "nearest") ... 171 if (strcmp (method, "linear") || strcmp (method, "nearest") ...
172 || strcmp (method, "pchip")) 172 || strcmp (method, "pchip"))
249 ## first order derivatives 249 ## first order derivatives
250 DX = __pchip_deriv__ (X, Z, 2); 250 DX = __pchip_deriv__ (X, Z, 2);
251 DY = __pchip_deriv__ (Y, Z, 1); 251 DY = __pchip_deriv__ (Y, Z, 1);
252 ## Compute mixed derivatives row-wise and column-wise, use the average. 252 ## Compute mixed derivatives row-wise and column-wise, use the average.
253 DXY = (__pchip_deriv__ (X, DY, 2) + __pchip_deriv__ (Y, DX, 1))/2; 253 DXY = (__pchip_deriv__ (X, DY, 2) + __pchip_deriv__ (Y, DX, 1))/2;
254 254
255 ## do the bicubic interpolation 255 ## do the bicubic interpolation
256 hx = diff (X); hx = hx(xidx); 256 hx = diff (X); hx = hx(xidx);
257 hy = diff (Y); hy = hy(yidx); 257 hy = diff (Y); hy = hy(yidx);
258 258
259 tx = (XI - X(xidx)) ./ hx; 259 tx = (XI - X(xidx)) ./ hx;
350 if (0 && isgriddata (XI) && isgriddata (YI')) 350 if (0 && isgriddata (XI) && isgriddata (YI'))
351 ZI = bicubic (X, Y, Z, XI (1, :), YI (:, 1), extrapval); 351 ZI = bicubic (X, Y, Z, XI (1, :), YI (:, 1), extrapval);
352 elseif (isgriddata (X) && isgriddata (Y')) 352 elseif (isgriddata (X) && isgriddata (Y'))
353 ## Allocate output 353 ## Allocate output
354 ZI = zeros (size (X)); 354 ZI = zeros (size (X));
355 355
356 ## Find inliers 356 ## Find inliers
357 inside = !(XI < X (1) | XI > X (end) | YI < Y (1) | YI > Y (end)); 357 inside = !(XI < X (1) | XI > X (end) | YI < Y (1) | YI > Y (end));
358 358
359 ## Scale XI and YI to match indices of Z 359 ## Scale XI and YI to match indices of Z
360 XI = (columns (Z) - 1) * (XI - X (1)) / (X (end) - X (1)) + 1; 360 XI = (columns (Z) - 1) * (XI - X (1)) / (X (end) - X (1)) + 1;
361 YI = (rows (Z) - 1) * (YI - Y (1)) / (Y (end) - Y (1)) + 1; 361 YI = (rows (Z) - 1) * (YI - Y (1)) / (Y (end) - Y (1)) + 1;
362 362
363 ## Start the real work 363 ## Start the real work
364 K = floor (XI); 364 K = floor (XI);
365 L = floor (YI); 365 L = floor (YI);
366 366
367 ## Coefficients 367 ## Coefficients
391 + AY1 .* AX_2 .* Z (sym_sub2ind (sz, L-1, K+2)) ... 391 + AY1 .* AX_2 .* Z (sym_sub2ind (sz, L-1, K+2)) ...
392 + AY1 .* AX_1 .* Z (sym_sub2ind (sz, L-1, K+1)) ... 392 + AY1 .* AX_1 .* Z (sym_sub2ind (sz, L-1, K+1)) ...
393 + AY1 .* AX0 .* Z (sym_sub2ind (sz, L-1, K)) ... 393 + AY1 .* AX0 .* Z (sym_sub2ind (sz, L-1, K)) ...
394 + AY1 .* AX1 .* Z (sym_sub2ind (sz, L-1, K-1)); 394 + AY1 .* AX1 .* Z (sym_sub2ind (sz, L-1, K-1));
395 ZI (!inside) = extrapval; 395 ZI (!inside) = extrapval;
396 396
397 else 397 else
398 error ("interp2: input data must have `meshgrid' format"); 398 error ("interp2: input data must have `meshgrid' format");
399 endif 399 endif
400 400
401 elseif (strcmp (method, "spline")) 401 elseif (strcmp (method, "spline"))
402 if (isgriddata (XI) && isgriddata (YI')) 402 if (isgriddata (XI) && isgriddata (YI'))
403 ZI = __splinen__ ({Y(:,1).', X(1,:)}, Z, {YI(:,1), XI(1,:)}, extrapval, 403 ZI = __splinen__ ({Y(:,1).', X(1,:)}, Z, {YI(:,1), XI(1,:)}, extrapval,
404 "spline"); 404 "spline");
405 else 405 else
406 error ("interp2: input data must have `meshgrid' format"); 406 error ("interp2: input data must have `meshgrid' format");
407 endif 407 endif
408 else 408 else
447 %! A=[13,-1,12;5,4,3;1,6,2]; 447 %! A=[13,-1,12;5,4,3;1,6,2];
448 %! x=[0,1,4]; y=[10,11,12]; 448 %! x=[0,1,4]; y=[10,11,12];
449 %! xi=linspace(min(x),max(x),17); 449 %! xi=linspace(min(x),max(x),17);
450 %! yi=linspace(min(y),max(y),26)'; 450 %! yi=linspace(min(y),max(y),26)';
451 %! mesh(xi,yi,interp2(x,y,A,xi,yi,'linear')); 451 %! mesh(xi,yi,interp2(x,y,A,xi,yi,'linear'));
452 %! [x,y] = meshgrid(x,y); 452 %! [x,y] = meshgrid(x,y);
453 %! hold on; plot3(x(:),y(:),A(:),"b*"); hold off; 453 %! hold on; plot3(x(:),y(:),A(:),"b*"); hold off;
454 454
455 %!demo 455 %!demo
456 %! [x,y,A] = peaks(10); 456 %! [x,y,A] = peaks(10);
457 %! x = x(1,:)'; y = y(:,1); 457 %! x = x(1,:)'; y = y(:,1);
458 %! xi=linspace(min(x),max(x),41); 458 %! xi=linspace(min(x),max(x),41);
459 %! yi=linspace(min(y),max(y),41)'; 459 %! yi=linspace(min(y),max(y),41)';
460 %! mesh(xi,yi,interp2(x,y,A,xi,yi,'linear')); 460 %! mesh(xi,yi,interp2(x,y,A,xi,yi,'linear'));
461 %! [x,y] = meshgrid(x,y); 461 %! [x,y] = meshgrid(x,y);
462 %! hold on; plot3(x(:),y(:),A(:),"b*"); hold off; 462 %! hold on; plot3(x(:),y(:),A(:),"b*"); hold off;
463 463
464 %!demo 464 %!demo
465 %! A=[13,-1,12;5,4,3;1,6,2]; 465 %! A=[13,-1,12;5,4,3;1,6,2];
466 %! x=[0,1,4]; y=[10,11,12]; 466 %! x=[0,1,4]; y=[10,11,12];
467 %! xi=linspace(min(x),max(x),17); 467 %! xi=linspace(min(x),max(x),17);
468 %! yi=linspace(min(y),max(y),26)'; 468 %! yi=linspace(min(y),max(y),26)';
469 %! mesh(xi,yi,interp2(x,y,A,xi,yi,'nearest')); 469 %! mesh(xi,yi,interp2(x,y,A,xi,yi,'nearest'));
470 %! [x,y] = meshgrid(x,y); 470 %! [x,y] = meshgrid(x,y);
471 %! hold on; plot3(x(:),y(:),A(:),"b*"); hold off; 471 %! hold on; plot3(x(:),y(:),A(:),"b*"); hold off;
472 472
473 %!demo 473 %!demo
474 %! [x,y,A] = peaks(10); 474 %! [x,y,A] = peaks(10);
475 %! x = x(1,:)'; y = y(:,1); 475 %! x = x(1,:)'; y = y(:,1);
476 %! xi=linspace(min(x),max(x),41); 476 %! xi=linspace(min(x),max(x),41);
477 %! yi=linspace(min(y),max(y),41)'; 477 %! yi=linspace(min(y),max(y),41)';
478 %! mesh(xi,yi,interp2(x,y,A,xi,yi,'nearest')); 478 %! mesh(xi,yi,interp2(x,y,A,xi,yi,'nearest'));
479 %! [x,y] = meshgrid(x,y); 479 %! [x,y] = meshgrid(x,y);
480 %! hold on; plot3(x(:),y(:),A(:),"b*"); hold off; 480 %! hold on; plot3(x(:),y(:),A(:),"b*"); hold off;
481 481
482 %!demo 482 %!demo
483 %! A=[13,-1,12;5,4,3;1,6,2]; 483 %! A=[13,-1,12;5,4,3;1,6,2];
484 %! x=[0,1,2]; y=[10,11,12]; 484 %! x=[0,1,2]; y=[10,11,12];
485 %! xi=linspace(min(x),max(x),17); 485 %! xi=linspace(min(x),max(x),17);
486 %! yi=linspace(min(y),max(y),26)'; 486 %! yi=linspace(min(y),max(y),26)';
487 %! mesh(xi,yi,interp2(x,y,A,xi,yi,'pchip')); 487 %! mesh(xi,yi,interp2(x,y,A,xi,yi,'pchip'));
488 %! [x,y] = meshgrid(x,y); 488 %! [x,y] = meshgrid(x,y);
489 %! hold on; plot3(x(:),y(:),A(:),"b*"); hold off; 489 %! hold on; plot3(x(:),y(:),A(:),"b*"); hold off;
490 490
491 %!demo 491 %!demo
492 %! [x,y,A] = peaks(10); 492 %! [x,y,A] = peaks(10);
493 %! x = x(1,:)'; y = y(:,1); 493 %! x = x(1,:)'; y = y(:,1);
494 %! xi=linspace(min(x),max(x),41); 494 %! xi=linspace(min(x),max(x),41);
495 %! yi=linspace(min(y),max(y),41)'; 495 %! yi=linspace(min(y),max(y),41)';
496 %! mesh(xi,yi,interp2(x,y,A,xi,yi,'pchip')); 496 %! mesh(xi,yi,interp2(x,y,A,xi,yi,'pchip'));
497 %! [x,y] = meshgrid(x,y); 497 %! [x,y] = meshgrid(x,y);
498 %! hold on; plot3(x(:),y(:),A(:),"b*"); hold off; 498 %! hold on; plot3(x(:),y(:),A(:),"b*"); hold off;
499 499
500 %!demo 500 %!demo
501 %! A=[13,-1,12;5,4,3;1,6,2]; 501 %! A=[13,-1,12;5,4,3;1,6,2];
502 %! x=[0,1,2]; y=[10,11,12]; 502 %! x=[0,1,2]; y=[10,11,12];
503 %! xi=linspace(min(x),max(x),17); 503 %! xi=linspace(min(x),max(x),17);
504 %! yi=linspace(min(y),max(y),26)'; 504 %! yi=linspace(min(y),max(y),26)';
505 %! mesh(xi,yi,interp2(x,y,A,xi,yi,'cubic')); 505 %! mesh(xi,yi,interp2(x,y,A,xi,yi,'cubic'));
506 %! [x,y] = meshgrid(x,y); 506 %! [x,y] = meshgrid(x,y);
507 %! hold on; plot3(x(:),y(:),A(:),"b*"); hold off; 507 %! hold on; plot3(x(:),y(:),A(:),"b*"); hold off;
508 508
509 %!demo 509 %!demo
510 %! [x,y,A] = peaks(10); 510 %! [x,y,A] = peaks(10);
511 %! x = x(1,:)'; y = y(:,1); 511 %! x = x(1,:)'; y = y(:,1);
512 %! xi=linspace(min(x),max(x),41); 512 %! xi=linspace(min(x),max(x),41);
513 %! yi=linspace(min(y),max(y),41)'; 513 %! yi=linspace(min(y),max(y),41)';
514 %! mesh(xi,yi,interp2(x,y,A,xi,yi,'cubic')); 514 %! mesh(xi,yi,interp2(x,y,A,xi,yi,'cubic'));
515 %! [x,y] = meshgrid(x,y); 515 %! [x,y] = meshgrid(x,y);
516 %! hold on; plot3(x(:),y(:),A(:),"b*"); hold off; 516 %! hold on; plot3(x(:),y(:),A(:),"b*"); hold off;
517 517
518 %!demo 518 %!demo
519 %! A=[13,-1,12;5,4,3;1,6,2]; 519 %! A=[13,-1,12;5,4,3;1,6,2];
520 %! x=[0,1,2]; y=[10,11,12]; 520 %! x=[0,1,2]; y=[10,11,12];
521 %! xi=linspace(min(x),max(x),17); 521 %! xi=linspace(min(x),max(x),17);
522 %! yi=linspace(min(y),max(y),26)'; 522 %! yi=linspace(min(y),max(y),26)';
523 %! mesh(xi,yi,interp2(x,y,A,xi,yi,'spline')); 523 %! mesh(xi,yi,interp2(x,y,A,xi,yi,'spline'));
524 %! [x,y] = meshgrid(x,y); 524 %! [x,y] = meshgrid(x,y);
525 %! hold on; plot3(x(:),y(:),A(:),"b*"); hold off; 525 %! hold on; plot3(x(:),y(:),A(:),"b*"); hold off;
526 526
527 %!demo 527 %!demo
528 %! [x,y,A] = peaks(10); 528 %! [x,y,A] = peaks(10);
529 %! x = x(1,:)'; y = y(:,1); 529 %! x = x(1,:)'; y = y(:,1);
530 %! xi=linspace(min(x),max(x),41); 530 %! xi=linspace(min(x),max(x),41);
531 %! yi=linspace(min(y),max(y),41)'; 531 %! yi=linspace(min(y),max(y),41)';
532 %! mesh(xi,yi,interp2(x,y,A,xi,yi,'spline')); 532 %! mesh(xi,yi,interp2(x,y,A,xi,yi,'spline'));
533 %! [x,y] = meshgrid(x,y); 533 %! [x,y] = meshgrid(x,y);
534 %! hold on; plot3(x(:),y(:),A(:),"b*"); hold off; 534 %! hold on; plot3(x(:),y(:),A(:),"b*"); hold off;
535 535
536 %!test % simple test 536 %!test % simple test
537 %! x = [1,2,3]; 537 %! x = [1,2,3];
538 %! y = [4,5,6,7]; 538 %! y = [4,5,6,7];
555 %! [X, Y] = meshgrid(x,y); 555 %! [X, Y] = meshgrid(x,y);
556 %! Orig = X.^2 + Y.^3; 556 %! Orig = X.^2 + Y.^3;
557 %! xi = [1:0.25:3]; yi = [4:0.25:7]'; 557 %! xi = [1:0.25:3]; yi = [4:0.25:7]';
558 %! Expected = interp2(x,y,Orig, xi, yi); 558 %! Expected = interp2(x,y,Orig, xi, yi);
559 %! Result = interp2(Orig,2); 559 %! Result = interp2(Orig,2);
560 %! 560 %!
561 %! assert(Result, Expected, 10*eps); 561 %! assert(Result, Expected, 10*eps);
562 562
563 %!test % matrix slice 563 %!test % matrix slice
564 %! A = eye(4); 564 %! A = eye(4);
565 %! assert(interp2(A,[1:4],[1:4]),[1,1,1,1]); 565 %! assert(interp2(A,[1:4],[1:4]),[1,1,1,1]);
578 %! assert(interp2(x,y,Orig, xi, yi),[NA,NA;NA,NA]); 578 %! assert(interp2(x,y,Orig, xi, yi),[NA,NA;NA,NA]);
579 %! assert(interp2(x,y,Orig, xi, yi,'linear', 0),[0,0;0,0]); 579 %! assert(interp2(x,y,Orig, xi, yi,'linear', 0),[0,0;0,0]);
580 580
581 %!test % for values at boundaries 581 %!test % for values at boundaries
582 %! A=[1,2;3,4]; 582 %! A=[1,2;3,4];
583 %! x=[0,1]; 583 %! x=[0,1];
584 %! y=[2,3]'; 584 %! y=[2,3]';
585 %! assert(interp2(x,y,A,x,y,'linear'), A); 585 %! assert(interp2(x,y,A,x,y,'linear'), A);
586 %! assert(interp2(x,y,A,x,y,'nearest'), A); 586 %! assert(interp2(x,y,A,x,y,'nearest'), A);
587 587
588 %!test % for Matlab-compatible rounding for 'nearest' 588 %!test % for Matlab-compatible rounding for 'nearest'