# 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

```