Deserializing 32-bit float in SWI-Prolog

Is there a way to convert a serialized float to a SWI-Prolog float, preferably without casting to C (I will do this if I need to)?

I am parsing a binary stream (OSC protocol). I get the 32-bit floating IEEE 754 as a list of 4 characters "codes". Now I want to combine this with a regular floating SWI-Prolog.

+4
source share
2 answers

There is a protobufs library in SWI-Prolog that has what you need float32_codes/2::

?- use_foreign_library(foreign(protobufs)).
true.

?- float32_codes(X,[0x2b,0x52,0x9a,0x44]).
X = 1234.5677490234375

?- float32_codes(1234.5678,A).
A = [43, 82, 154, 68].
+4
source

I also have a standalone Prolog approach (using SWI-Prolog unsure about portability):

float_bits(_,  N, -1,  _,   N) :- !.
float_bits(Bs, N, Bit, Div, Ans) :-
    Nn is N + (getbit(Bs, Bit) * Div),
    DivN is Div / 2,
    BitN is Bit - 1,
    float_bits(Bs, Nn, BitN, DivN, Ans).
float_bits(Bs, N) :- float_bits(Bs, 1, 22, 0.5, N).

floating(Fl) -->
    [A, B, C, D],
    { [A,B,C,D] ins 0..255,
      Sign is (-1)**((A /\ 0b1000_0000) >> 7),
      Exp_ is (A /\ 0b0111_1111) << 1 + (B /\ 0b1000_0000) >> 7,
      Exp is 2**(Exp_ - 127),
      FracBits is (B /\ 0b0111_1111)<<16 + C<<8 + D,
      float_bits(FracBits, Frac),
      Fl is Sign * Exp * Frac }.

Test example:

    ?- phrase(floating(0.15625), 
              [0b0011_1110, 0b0010_0000, 0b0000_0000, 0b00000000]).
    true.
0
source

Source: https://habr.com/ru/post/1685806/


All Articles