mirror of
https://github.com/c-sooyoung/fold_slice.git
synced 2026-09-17 23:59:11 +09:00
215 lines
7.7 KiB
Matlab
215 lines
7.7 KiB
Matlab
% halfprecision converts IEEE 754 floating point to half precision IEEE 754r
|
|
%******************************************************************************
|
|
%
|
|
% MATLAB (R) is a trademark of The Mathworks (R) Corporation
|
|
%
|
|
% Function: halfprecision
|
|
% Filename: halfprecision.c
|
|
% Programmer: James Tursa
|
|
% Version: 1.0
|
|
% Date: March 3, 2009
|
|
% Copyright: (c) 2009 by James Tursa, All Rights Reserved
|
|
%
|
|
% This code uses the BSD License:
|
|
%
|
|
% Redistribution and use in source and binary forms, with or without
|
|
% modification, are permitted provided that the following conditions are
|
|
% met:
|
|
%
|
|
% * Redistributions of source code must retain the above copyright
|
|
% notice, this list of conditions and the following disclaimer.
|
|
% * Redistributions in binary form must reproduce the above copyright
|
|
% notice, this list of conditions and the following disclaimer in
|
|
% the documentation and/or other materials provided with the distribution
|
|
%
|
|
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
% POSSIBILITY OF SUCH DAMAGE.
|
|
%
|
|
% halfprecision converts the input argument to/from a half precision floating
|
|
% point bit pattern corresponding to IEEE 754r. The bit pattern is stored in a
|
|
% uint16 class variable. Please note that halfprecision is *not* a class. That
|
|
% is, you cannot do any arithmetic with the half precision bit patterns.
|
|
% halfprecision is simply a function that converts the IEEE 754r half precision
|
|
% bit pattern to/from other numeric MATLAB variables. You can, however, take
|
|
% the half precision bit patterns, convert them to single or double, do the
|
|
% operation, and then convert the result back manually.
|
|
%
|
|
% 1 bit sign bit
|
|
% 5 bits exponent, biased by 15
|
|
% 10 bits mantissa, hidden leading bit, normalized to 1.0
|
|
%
|
|
% Special floating point bit patterns recognized and supported:
|
|
%
|
|
% All exponent bits zero:
|
|
% - If all mantissa bits are zero, then number is zero (possibly signed)
|
|
% - Otherwise, number is a denormalized bit pattern
|
|
%
|
|
% All exponent bits set to 1:
|
|
% - If all mantissa bits are zero, then number is +Infinity or -Infinity
|
|
% - Otherwise, number is NaN (Not a Number)
|
|
%
|
|
% Building:
|
|
%
|
|
% halfprecision requires that a mex routine be built (one time only). This
|
|
% process is typically self-building the first time you call the function
|
|
% as long as you have the files halfprecision.m and halfprecision.c in the
|
|
% same directory somewhere on the MATLAB path. If you need to manually build
|
|
% the mex function, here are the commands:
|
|
%
|
|
% >> mex -setup
|
|
% (then follow instructions to select a C / C++ compiler of your choice)
|
|
% >> mex halfprecision.c
|
|
%
|
|
% If you have an older version of MATLAB, you may need to use this command:
|
|
%
|
|
% >> mex -DDEFINEMWSIZE halfprecision.c
|
|
%
|
|
% Syntax
|
|
%
|
|
% B = halfprecision(A)
|
|
% C = halfprecision(B,S)
|
|
% halfprecision(B,'disp')
|
|
%
|
|
% Description
|
|
%
|
|
% A = a MATLAB numeric array, char array, or logical array.
|
|
%
|
|
% B = the variable A converted into half precision floating point bit pattern.
|
|
% The bit pattern will be returned as a uint16 class variable. The values
|
|
% displayed are simply the bit pattern interpreted as if it were an unsigned
|
|
% 16-bit integer. To see the halfprecision values, use the 'disp' option, which
|
|
% simply converts the bit patterns into a single class and then displays them.
|
|
%
|
|
% C = the half precision floating point bit pattern in B converted into class S.
|
|
% B must be a uint16 or int16 class variable.
|
|
%
|
|
% S = char string naming the desired class (e.g., 'single', 'int32', etc.)
|
|
% If S = 'disp', then the floating point bit values are simply displayed.
|
|
%
|
|
% Examples
|
|
%
|
|
% >> a = [-inf -1e30 -1.2 NaN 1.2 1e30 inf]
|
|
% a =
|
|
% 1.0e+030 *
|
|
% -Inf -1.0000 -0.0000 NaN 0.0000 1.0000 Inf
|
|
%
|
|
% >> b = halfprecision(a)
|
|
% b =
|
|
% 64512 64512 48333 65024 15565 31744 31744
|
|
%
|
|
% >> halfprecision(b,'disp')
|
|
% -Inf -Inf -1.2002 NaN 1.2002 Inf Inf
|
|
%
|
|
% >> halfprecision(b,'double')
|
|
% ans =
|
|
% -Inf -Inf -1.2002 NaN 1.2002 Inf Inf
|
|
%
|
|
% >> 2^(-24)
|
|
% ans =
|
|
% 5.9605e-008
|
|
%
|
|
% >> halfprecision(ans)
|
|
% ans =
|
|
% 1
|
|
%
|
|
% >> halfprecision(ans,'disp')
|
|
% 5.9605e-008
|
|
%
|
|
% >> 2^(-25)
|
|
% ans =
|
|
% 2.9802e-008
|
|
%
|
|
% >> halfprecision(ans)
|
|
% ans =
|
|
% 1
|
|
%
|
|
% >> halfprecision(ans,'disp')
|
|
% 5.9605e-008
|
|
%
|
|
% >> 2^(-26)
|
|
% ans =
|
|
% 1.4901e-008
|
|
%
|
|
% >> halfprecision(ans)
|
|
% ans =
|
|
% 0
|
|
%
|
|
% >> halfprecision(ans,'disp')
|
|
% 0
|
|
%
|
|
% Note that the special cases of -Inf, +Inf, and NaN are handled correctly.
|
|
% Also, note that the -1e30 and 1e30 values overflow the half precision format
|
|
% and are converted into half precision -Inf and +Inf values, and stay that
|
|
% way when they are converted back into doubles.
|
|
%
|
|
% For the denormalized cases, note that 2^(-24) is the smallest number that can
|
|
% be represented in half precision exactly. 2^(-25) will convert to 2^(-24)
|
|
% because of the rounding algorithm used, and 2^(-26) is too small and underflows
|
|
% to zero.
|
|
%
|
|
%**************************************************************************
|
|
|
|
function varargout = halfprecision(varargin)
|
|
disp(' ');
|
|
disp('You must build the mex routine before you can use halfprecision.');
|
|
disp('Attempting to do so now ...');
|
|
disp(' ');
|
|
mname = mfilename('fullpath');
|
|
cname = [mname '.c'];
|
|
if( isempty(dir(cname)) )
|
|
disp('Cannot find the file halfprecision.c in the same directory as the');
|
|
disp('file halfprecision.m. Please ensure that they are in the same');
|
|
disp('directory and try again. The following file was not found:');
|
|
disp(' ');
|
|
disp(cname);
|
|
disp(' ');
|
|
error('Unable to compile halprecision.c');
|
|
else
|
|
disp(['Found file halfprecision.c in ' cname]);
|
|
disp(' ');
|
|
disp('Now attempting to compile ...');
|
|
disp('(If prompted, please press the Enter key and then select any C/C++');
|
|
disp('compiler that is available, such as lcc.)');
|
|
disp(' ');
|
|
disp(['mex(''' cname ''')']);
|
|
disp(' ');
|
|
try
|
|
mex(cname);
|
|
disp('mex halfprecision.c build completed ... you may now use halfprecision.');
|
|
disp(' ');
|
|
catch
|
|
disp(' ');
|
|
disp('Well, *that* didn''t work ... now trying it with mwSize defined ...');
|
|
disp(' ');
|
|
try
|
|
disp(' ');
|
|
disp(['mex(''-DDEFINEMWSIZE'',''' cname ''')']);
|
|
disp(' ');
|
|
mex('-DDEFINEMWSIZE',cname);
|
|
disp('mex halfprecision.c build completed ... you may now use halfprecision.');
|
|
disp(' ');
|
|
catch
|
|
disp('Hmmm ... That didn''t work either.');
|
|
disp(' ');
|
|
disp('The mex command failed. This may be because you have already run');
|
|
disp('mex -setup and selected a non-C compiler, such as Fortran. If this');
|
|
disp('is the case, then rerun mex -setup and select a C/C++ compiler.');
|
|
disp(' ');
|
|
error('Unable to compile halprecision.c');
|
|
end
|
|
end
|
|
end
|
|
if false
|
|
varargout = varargin; % Get rid of the lint message
|
|
end
|
|
end
|