Code covered by the BSD License  

Highlights from
IEEE 754r Half Precision floating point converter

IEEE 754r Half Precision floating point converter

by

James Tursa (view profile)

 

04 Mar 2009 (Updated )

Converts MATLAB or C variables to/from IEEE 754r Half Precision floating point bit pattern.

halfprecision(varargin)
% 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

Contact us