How to convert half-precision number into hexadecimal representation?

25 views (last 30 days)
Hi,
I am using matlab 2019B with support for complex half-precision operations. I want to store my results in a file but fwrite doesn't support class half. Some workaround is to convert to hex and then store as uint16. The problem is that num2hex also doesn't support half class. One way to obtain hexadecimal representation I have found is to use format hex, but parsing output string is not a solution for me.
My question is - Is there any native posibility to store half-precission numbers if file, or convert to hexadecimal representation for further processing?
Best Regards
Adam

Accepted Answer

James Tursa
James Tursa on 24 Apr 2020
Edited: James Tursa on 25 Apr 2020
I don't have R2019b installed so I don't know how half precision numbers are stored, but can you use typecast:
h = your half precision variable
u16 = typecast(h,'uint16');
Another option is a mex routine, but I would need to know how the half precision values are stored first.
EDIT
I just checked, and unfortunately the new half precision type is not a fundamental numeric type like double or uint16 ... it is an opaque type like OOP classdef objects. So even though isnumeric(half) returns true, half precision variables are not stored the same as the native numeric variables are. The data areas are hidden.
I have no idea why TMW would choose to implement a basic numeric type this way, but they must have their reasons. The half precision type is fundamentally different from all of the other numeric types. Not suprisingly, the typecast( ) function does not work since the storage scheme is fundamentally different. This also makes a mex option out of the question since the data area is hidden. What a pain ... why couldn't they have just made it compatible with all the other numeric types??? THERE WILL BE NO WAY TO EFFICIENTLY WORK WITH HALF VARIBLES IN A MEX ROUTINE BECAUSE OF THIS! (yes I am shouting)
SOLUTION
For your purpose, you only need the hex patterns or equivalent bit patterns to write out. So I can offer my C-mex code for this, which can be found here:
You would convert your half precision variable to single, then call my C-mex routine to turn it into the uint16 half precision bit pattern. Then you can write that uint16 variable directly to a file in binary with fwrite( ). I just need to check to see if it still works in later versions of MATLAB. I will get back to you ...
UPDATE
I downloaded my halfprecision C-mex file and it seems to compile and run OK. Just don't use the -R2018a mex option because the code isn't updated yet for R2018a+. My halfprecision C code will also handle the inf, nan, and denorm patterns just fine. You would compile it as follows:
mex halfprecision.c
Sample run:
>> version
ans =
'9.7.0.1190202 (R2019b)'
>> halfpi = half(pi) % The MATLAB half class
halfpi =
half
3.1406250 % MATLAB is apparently using the single display code for this
>> hp = halfprecision(pi) % my C-mex routine ...
hp =
uint16 % ... returns a uint16 variable that contains the half precision bit pattern
16968
>> halfprecision(hp,'disp') % my C-mex routine has a display option
3.1406
>> halfprecision(hp,'single') % my C-mex routine can convert it back into other classes
ans =
single
3.1406250
>> sprintf('%04x',hp) % If you want the hex values as ASCII text, do this
ans =
'4248'
>>
>> halfinf = half(inf)
halfinf =
half
Inf
>> hinf = halfprecision(inf)
hinf =
uint16
31744
>> halfprecision(hinf,'disp')
Inf
>> halfprecision(hinf,'single')
ans =
single
Inf
>> sprintf('%04x',hinf)
ans =
'7c00'
>>
>> halfnan = half(nan)
halfnan =
half
NaN
>> hnan = halfprecision(nan)
hnan =
uint16
65024
>> halfprecision(hnan,'disp')
NaN
>> halfprecision(hnan,'single')
ans =
single
NaN
>> sprintf('%04x',hnan)
ans =
'fe00'
>> format hex
>> halfpi
halfpi =
half
4248
>> halfinf
halfinf =
half
7c00
>> halfnan
halfnan =
half
fe00
  2 Comments
Adam Przybyla
Adam Przybyla on 25 Apr 2020
Hi,
thanks a lot for your answer.
My workaround for this problem was to write simple mex based on http://half.sourceforge.net/ half-precision implementation. It works well but I just doubted it couldn't be done by Matlab itself.
I've already seen your solution when I tried to find an answer to my doubts. Many links lead to that site :)
I keep fingers crossed that in next releases it will be supported.
James Tursa
James Tursa on 1 Jul 2020
Update: My FEX half precision code has been updated for R2018a+, and my FEX num2strexact submission has been updated for half precision inputs as well.

Sign in to comment.

More Answers (1)

Krishna Bindumadhavan
Krishna Bindumadhavan on 6 May 2020
You can use half.typecast() and storedInteger functions as a workaround to convert to and from half precision and the underlying uint16 storage.
ex.
>>storedInteger(half(100))
ans =
uint16
22080
>>half.typecast(ans)
ans =
half
100
Appreciate your feedback regarding typecast,fwrite,num2hex, and mxArray limitations. We will consider better support for these in a future release.
Best Regards,
Krishna.
  1 Comment
James Tursa
James Tursa on 6 May 2020
Edited: James Tursa on 6 May 2020
Thanks!
I would note that unlike the typecast( ) function for doubles and singles which produces shared data copies, the storedInteger( ) and half.typecast( ) functions listed above produce deep data copies. E.g.,
>> h = half(rand(1,100000000/2,'single'));
>> whos
Name Size Bytes Class Attributes
h 1x50000000 100000000 half
>> memory
Maximum possible array: 18314 MB (1.920e+10 bytes) *
Memory available for all arrays: 18314 MB (1.920e+10 bytes) *
Memory used by MATLAB: 1992 MB (2.088e+09 bytes)
Physical Memory (RAM): 8088 MB (8.481e+09 bytes)
* Limited by System Memory (physical + swap file) available.
>> s = storedInteger(h);
>> memory
Maximum possible array: 18170 MB (1.905e+10 bytes) *
Memory available for all arrays: 18170 MB (1.905e+10 bytes) *
Memory used by MATLAB: 2097 MB (2.199e+09 bytes)
Physical Memory (RAM): 8088 MB (8.481e+09 bytes)
* Limited by System Memory (physical + swap file) available.
>> H = half.typecast(s);
>> memory
Maximum possible array: 18128 MB (1.901e+10 bytes) *
Memory available for all arrays: 18128 MB (1.901e+10 bytes) *
Memory used by MATLAB: 2204 MB (2.311e+09 bytes)
Physical Memory (RAM): 8088 MB (8.481e+09 bytes)
* Limited by System Memory (physical + swap file) available.
You can see in the above that the 100MB half variable h gets deep data copied for these steps (i.e., the Memory used by MATLAB increases by 100MB). This is an example of what I hope can be avoided in future versions of MATLAB. Shared data copy methods to get at the underlying data, and pointer access to the data inside mex routines. Making half a simple numeric class instead of an opaque class is one way to accomplish this.

Sign in to comment.

Products


Release

R2019b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!