function Y = round2dp(X,DcP,FnH)
% Round a numeric to given decimal places. Choose any rounding function.
%
% (c) 2013 Stephen Cobeldick
%
% Round to given decimal places. X may be an N-D matrix. The
% default rounding method is MATLAB's "round" function: an alternative
% rounding method may be selected by providing a function handle.
% The decimal places may be defined by a numeric scalar or matrix:
% positive/negative values round to the right/left of the decimal point.
% For complex X, the imaginary and real parts are rounded independently.
%
% Syntax:
% Y = round2dp(X) % Round to integer, use MATLAB's "round".
% Y = round2dp(X,DcP) % Select decimal-places, use MATLAB's "round".
% Y = round2dp(X,DcP,FnH) % Select decimal-places, use any rounding function.
%
% See also ROUND2SF ROUND2DN ROUND2UP ROUND2EV ROUND2OD ROUND2RA ROUND2ZE PREFNUM DATEROUND CEIL FLOOR FIX ROUND
%
% ### Rounding Functions ###
%
% Function |Description: |Example Values:
% Name: |Round decimal digits... |-3.5|-2.5|-1.5|-0.5|0.5|1.5|2.5|3.5
% ---------|-----------------------------------|----|----|----|----|---|---|---|---
% floor |all down (towards minus infinity) |-4 |-3 |-2 |-1 |0 |1 |2 |3
% ceil |all up (towards plus infinity) |-3 |-2 |-1 | 0 |1 |2 |3 |4
% fix |all towards zero |-3 |-2 |-1 | 0 |0 |1 |2 |3
% round * |half away from zero |-4 |-3 |-2 |-1 |1 |2 |3 |4 *
% ---------|-----------------------------------|----|----|----|----|---|---|---|---
% round2ze |half towards zero |-3 |-2 |-1 | 0 |0 |1 |2 |3
% round2dn |half down (towards minus infinity) |-4 |-3 |-2 |-1 |0 |1 |2 |3
% round2up |half up (towards plus infinity) |-3 |-2 |-1 | 0 |1 |2 |3 |4
% round2ev |half towards nearest even integer |-4 |-2 |-2 | 0 |0 |2 |2 |4
% round2od |half towards nearest odd integer |-3 |-3 |-1 |-1 |1 |1 |3 |3
% round2ra |half randomly (stochastic rounding)|-4 |-2 |-1 | 0 |0 |2 |3 |3 !
% ---------|-----------------------------------|----|----|----|----|---|---|---|---
%
% ### Examples ###
%
% round2dp([1111,222.2,33.33,4.444,0.5555])
% ans = [1111,222,33,4,1]
%
% round2dp([1111,222.2,33.33,4.444,0.5555],-1)
% ans = [1110,220,30,0,0]
%
% round2dp([1111,222.2,33.33,4.444,0.5555],0)
% ans = [1111,222,33,4,1]
%
% round2dp([1111,222.2,33.33,4.444,0.5555],1)
% ans = [1111,222.2,33.3,4.4,0.6]
%
% round2dp([1111,222.2,33.33,4.444,0.5555],2)
% ans = [1111,222.2,33.33,4.44,0.56]
%
% round2dp([1111,222.2,33.33,4.444,0.5555],2,@ceil)
% ans = [1111,222.2,33.33,4.45,0.56]
%
% round2dp([6.6666,6.6666;6.6666,6.6666],[1,2;3,4])
% ans = [6.7,6.67;6.667,6.6666]
%
% ### Inputs & Outputs ###
%
% Inputs (default=*):
% X = Numeric array of any size, with elements to be rounded.
% DcP = Numeric scalar, decimal places, -Inf<N<Inf, 0*.
% = Numeric array, same size as X, decimal-places for each element of X.
% FnH = Function handle of any rounding function, eg: @fix, @round*.
%
% Output:
% Y = Numeric array, same size as X, with rounded elements of X.
%
% Inputs = (X,DcP*,FnH*)
% Output = Y
if nargin<3
% Default rounding function:
FnH = @round;
else
% Check user supplied rounding function:
assert(isa(FnH,'function_handle'),'Input "FnH" must be a function handle.')
T = FnH([-1000.9,-100.2,-10.7,-1.4,0.5,1.6,10.3,100.8,1000.1]);
assert(isnumeric(T)&&all(rem(T,1)==0),'Function "FnH" must return a rounded numeric.')
end
%
if nargin<2
% Default number of decimal places:
DcP = 0;
else
assert(all(isfinite(DcP(:)))&&isreal(DcP),'Input DcP must be real numeric.')
end
%
if isreal(X)% Real
% Adjust, Round, Unadjust:
Y = FnH(X.*10.^DcP).*10.^-DcP;
else% Complex (in case FnH does not round real+imaginary separately)
% Adjust, Round, Unadjust:
Y = complex(FnH(real(X).*10.^DcP).*10.^-DcP,FnH(imag(X).*10.^DcP).*10.^-DcP);
end
%----------------------------------------------------------------------End!