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