Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Perl 6, how can I convert from raw bytes to floating point using the NativeCall interface?

From this conversation in the Perl 6 IRC channel and a question posted by Martin Barth, I'm trying to reproduce this C code using the Perl6 NativeCall interface, which is used with that purpose. This is what I have tried:

use NativeCall;

my uint32 $num = .new;
my num32 $float = .new: Num(1.0);

sub memcpy(num32 $float, uint32 $num, int32 $size) is native('Str') { * };

memcpy($float,$num,4);
say $num;

This yields an error:

This type cannot unbox to a native integer: P6opaque, Any

Which I interpret as, well, you have declared this as an Integer, I can't turn it into raw memory so that it can be copied from here to there.

This was only a possible way of answering the more general question by Martin Barth: how to turn raw bytes into a floating point number. Maybe there's other way of doing that, but in any case I'd be curious to find out how to turn C programs into NativeCall equivalents.

Update: in the meantime, here's the original question this other post tries to be a solution for.

like image 423
jjmerelo Avatar asked Apr 29 '18 11:04

jjmerelo


People also ask

Is Perl a scalar language?

Perl supports platform-native floating-point as scalar values; in practice this usually means IEEE 754 double precision. Exact Types. Perl can also store decimal numbers as strings, but the builtin arithmetic operators will convert them to integer or floating-point values to perform the operation.

How to parse binary data with Perl?

How to parse binary data with Perl. 1 1. Open a binary filehandle. Start things off right by opening a filehandle to binary file: use autodie; open my $fh, '<:raw', ... 2 2. Read a few bytes. 3 3. Unpack bytes into variables.

Can Perl store decimal numbers as strings?

Perl can also store decimal numbers as strings, but the builtin arithmetic operators will convert them to integer or floating-point values to perform the operation. The Math::BigFloat extension provides an arbitrary-precision decimal type:

What type of data can Perl store?

Perl supports platform-native floating-point as scalar values; in practice this usually means IEEE 754 double precision. Perl can also store decimal numbers as strings, but the builtin arithmetic operators will convert them to integer or floating-point values to perform the operation.


1 Answers

Using a union (where all fields share the same memory space) is perhaps the most natural way. Declare a union like this:

my class Convertor is repr<CUnion> {
    has uint32 $.i is rw;
    has num32 $.n is rw;
}

And then use it to do conversion:

my $c = Convertor.new;
$c.i = 0b1000010111101101100110011001101;
say $c.n  # 123.4000015258789

One other issue unrelated to the meat of the question, but present in the posted code: the native integer and number times never need to have a .new done on them, because they are not object types. This:

my uint32 $num = .new;

Should just be:

my uint32 $num;

And:

my num32 $float = .new: Num(1.0);

Should just be:

my num32 $float = 1e0;

The use of the e exponent is what makes a literal a float in Perl 6.

like image 174
Jonathan Worthington Avatar answered Oct 18 '22 19:10

Jonathan Worthington