On 19-04-16 10:21, Elizabeth Mattijsen wrote:
FWIW, I’ll take PR’s for the PackUnpack distribution to make ‘f’ and ‘d’ work  
:-)


Hi Elizabeth,

For the PackUnpack distro this might come in handy... or might go in the examples corner?

Done some experiments and looks well. Please check the attachment for encoding/decoding of doubles. decode-double has also an index in the buffer to pull out a specific spot in the buffer where the encoded double should be. The code is made from snippets from Timo Paulsen and
David Warren.

You might want to know how much faster it has become. Well it's not that much of an improvement, only encoding a double is about 4 times faster. The decoding only 1.13 times.

emulated encoded
3000 runs total time = 7.211524 s, 0.002404 s per run, 416.000809 runs per s

native encoded
3000 runs total time = 1.720918 s, 0.000574 s per run, 1743.256109 runs per s

emulated decode
3000 runs total time = 1.038615 s, 0.000346 s per run, 2888.461538 runs per s

native decode
3000 runs total time = 0.918133 s, 0.000306 s per run, 3267.498734 runs per s


Before I pat myself on the back for the 'fast' emulated encode/decode already in place in the BSON package the above results might mean that the native routines can be done better.

Regards,
Marcel


#!/usr/bin/env perl6

use v6.c;
use NativeCall;

say 'little endian: ', little-endian;

for ( 0.3e3, 0.233333333, -20.45e-20, Inf, NaN) -> $r {

  say "Encode $r";

  my Buf $b = encode-double(Num.new($r));
  say $b.list.fmt('%02x');

  say "Decoded num = ", decode-double( $b, 0);
}

#-----------------------------------------------------------------------------
# encode Num in buf little endian
#
sub encode-double ( Num:D $r --> Buf ) {

  my CArray[num64] $da .= new($r);
  my $list = nativecast( CArray[uint8], $da)[^8];
  if little-endian() {
    Buf[uint8].new($list);
  }

  else {
    Buf[uint8].new($list.reverse);
  }
}

#-----------------------------------------------------------------------------
# decode to Num from buf little endian
#
sub decode-double ( Buf:D $b, Int:D $index --> Num ) {

  my Buf[uint8] $ble;
  my $list = $b.list;
  if little-endian() {
    $ble .= new($b.subbuf( $index, 8));
  }

  else {
    $ble .= new($b.subbuf( $index, 8).reverse);
  }

  nativecast( CArray[num64], $ble)[0];
}

#-----------------------------------------------------------------------------
sub little-endian ( --> Bool ) {

  my $i = CArray[uint32].new: 1;
  my $j = nativecast( CArray[uint8], $i);

  $j[0] == 0x01;
}

Reply via email to