Source code for irfpy.util.minifloat

r''' This module provides a routines to convert minifloats.

.. codeauthor:: Martin Wieser


You may also find document:
https://mrob.com/pub/math/floatformats.html#microfloat

Functions to convert between f8 minifloats and integers.
minifloats are 8 bit in size and have the following structure:
The names used are of historical origin
    
====== ======= ======= =====================  =============================
Name   s.e.m   Excess  Integer range covered  Used
------ ------- ------- ---------------------  -----------------------------
f8     0.4.4   -4      0 to 507903            ICA, IMA, JDC
n8     1.4.3   -4      -2xxxxx to +2xxxxx     JDC
====== ======= ======= =====================  =============================

- s: sign bits
- e: exponent bits
- m: mantissa bits

Special case:

====== ======= ======= =====================  =============================
Name   s.e.m   Excess  Integer range covered  Used
------ ------- ------- ---------------------  -----------------------------
s8     0.2.6   -3      0 to 951               JDC, no denormals, +64 offset
====== ======= ======= =====================  =============================
'''

import logging
_logger = logging.getLogger(__name__)


[docs]def u24_f8(u24): """ Convert an 24 bit integer to a f8 minifloat. In case of overflow 0xFF is returned """ if u24 > 507904: return 0xFF elif u24 < 0x10: return u24 else: e = 1 m = u24 while m >= 0x20: m = m >> 1 e = e + 1 # x is now 0x10 .. 0x1F m = m & 0xF # mask away 0x10 return (e << 4) + m
[docs]def f8_u16(f8): """ Convert a f8 minifloat to 16-bit integer. In case of overflow 0xFFFF is returned """ e = f8 & 0xF0 if e < 0x10: return f8 e = (e >> 4) - 1 if e > 11: return 0xFFFF return ((f8 & 0xF) | 0x10) << e
[docs]def f8_u24(f8): """ Convert a f8 minifloat to 24-bit integer. no overflow possible """ e = f8 & 0xF0 if e < 0x10: return f8 e = (e >> 4) - 1 return ((f8 & 0xF) | 0x10) << e
#%% n8
[docs]def i24_n8(i24): """ Convert an 24 bit signed integer to a n8 minifloat. In case of overflow 0xFF is returned """ if i24 > 229376: return 0x7F # +INF elif i24 < -229377: return 0x80 # -INF elif i24 < 8 and i24 >=-8: #denormals return i24 else: e = 1 m = i24 while m >= 0x20: m = m >> 1 e = e + 1 # x is now 0x10 .. 0x1F m = m & 0xF # mask away 0x10 return (e << 4) + m
#def n8_i16(f8): # """ Convert a n8 minifloat to 16-bit signed integer. In case of overflow 0xFFFF is returned # """ # # e = f8 & 0xF0 # if e < 0x10: # return f8 # e = (e >> 4) - 1 # if e > 11: # return 0xFFFF # return ((f8 & 0xF) | 0x10) << e # # #def n8_i24(f8): # """ Convert a n8 minifloat to 24-bit signed integer. no overflow possible # """ # e = f8 & 0xF0 # if e < 0x10: # return f8 # e = (e >> 4) - 1 # return ((f8 & 0xF) | 0x10) << e #%% s8
[docs]def u16_s8(u16): """ Convert an 16 bit integer to a s8 minifloat. s8 is optimized for JDC D-channel data no denormals, +64 offset In case of overflow 0xFF is returned """ if u16 > 951: return 0xFF elif u16 < 64: return u16 elif u16 < 192: return ((u16-64) >> 1) + 64 elif u16 < 448: return ((u16-192) >> 2) + 128 else: return ((u16-448) >> 3) + 192
[docs]def s8_u16(s8): """ Convert a s8 minifloat to 16-bit integer. """ if s8 < 64: return s8 elif s8 < 128: return ((s8-64) << 1) + 64 elif u16 < 448: return ((s8-128) << 2) + 192 else: return ((s8-192) << 3) + 448