use strict; use warnings; use Inline "C"; use Data::Peek; use Benchmark qw( cmpthese ); my @src = map { pack "C*" => map { int rand 256 } 0 .. 23 } 0 .. 127;#8192; print STDERR "First line of the compressed data ...\n"; DHexDump $src[0]; for (unpack "(a3)*", $src[0]) { DHexDump $_; my $bits = unpack "B*", $_; (my $b8 = substr $bits, 0, 48) =~ s/(.{8})/$1 /g; (my $b6 = substr $bits, 0, 48) =~ s/(.{6})/$1 /g; print STDERR " $b8\n $b6\n"; } sub uu { map { map { ($_ - 32) & 63 } unpack "xC*" => $_ } split m/ *\n/ => pack "u" => shift; } # uu { my @lut; for (0 .. 0b111111) { $lut[$_ << 18] = $_; $lut[$_ << 12] = $_; $lut[$_ << 6] = $_; $lut[$_ ] = $_; } sub mlut { map { my $v = unpack "N", "\00$_\x00\x00"; ($lut[$v & 0b111111_000000_000000_000000], $lut[$v & 0b000000_111111_000000_000000], $lut[$v & 0b000000_000000_111111_000000], $v & 0b000000_000000_000000_111111); } unpack "(a3)*" => shift; } # mlut } { my $m0 = 0b111111_000000_000000_000000; my $m1 = 0b000000_111111_000000_000000; my $m2 = 0b000000_000000_111111_000000; my $m3 = 0b000000_000000_000000_111111; sub asu { map {my $b = unpack "N", "\x00$_\x00\x00"; ( ($b & $m0) >> 18, ($b & $m1) >> 12, ($b & $m2) >> 6, ($b & $m3) ) } unpack "(a3)*" => shift; } # asu } my @dst; @dst = map { uu ($_) } @src; print STDERR "$#dst E\n"; print STDERR "uu: (@dst[0..31] ...\n @dst[4073..4095])\n"; @dst = map { asu ($_) } @src; print STDERR "asu: (@dst[0..31] ...\n @dst[4073..4095])\n"; @dst = map { mlut ($_) } @src; print STDERR "mlut: (@dst[0..31] ...\n @dst[4073..4095])\n"; @dst = map { uic ($_) } @src; print STDERR "uic: (@dst[0..31] ...\n @dst[4073..4095])\n"; @dst = map { uicm ($_) } @src; print STDERR "uicm: (@dst[0..31] ...\n @dst[4073..4095])\n"; my @b = uicb_init (32); @dst = map { uicb ($_); map { $$_ } @b } @src; print STDERR "uicb: (@dst[0..31] ...\n @dst[4073..4095])\n"; cmpthese (-2, { uu => sub { uu ($_) for @src; }, asu => sub { asu ($_) for @src; }, mlut => sub { mlut ($_) for @src; }, uic => sub { uic ($_) for @src; }, uicm => sub { uicm ($_) for @src; }, uicb => sub { uicb ($_) for @src; }, }); __END__ __C__ void uic (SV *src) { int i = 0; STRLEN l; unsigned char *s = (unsigned char *)SvPV (src, l); inline_stack_vars; inline_stack_reset; while (i < l) { int n = (s[i] >> 2) & 0x3f; inline_stack_push (newSViv (n)); n = (s[i++] & 0x03) << 4; n |= (s[i] >> 4) & 0x0f; inline_stack_push (newSViv (n)); n = (s[i++] & 0x0f) << 2; n |= (s[i] >> 6) & 0x03; inline_stack_push (newSViv (n)); n = s[i++] & 0x3f; inline_stack_push (newSViv (n)); } inline_stack_done; } /* uic */ void uicm (SV *src) { int i = 0; STRLEN l; unsigned char *s = (unsigned char *)SvPV (src, l); inline_stack_vars; inline_stack_reset; while (i < l) { int n = (s[i] >> 2) & 0x3f; inline_stack_push (sv_2mortal (newSViv (n))); n = (s[i++] & 0x03) << 4; n |= (s[i] >> 4) & 0x0f; inline_stack_push (sv_2mortal (newSViv (n))); n = (s[i++] & 0x0f) << 2; n |= (s[i] >> 6) & 0x03; inline_stack_push (sv_2mortal (newSViv (n))); n = s[i++] & 0x3f; inline_stack_push (sv_2mortal (newSViv (n))); } inline_stack_done; } /* uicm */ SV **uicb_sv; void uicb_init (int n) { int i; inline_stack_vars; inline_stack_reset; uicb_sv = (SV **)calloc (sizeof (SV *), n); for (i = 0; i < n; i++) { inline_stack_push (newRV (uicb_sv[i] = newSViv (i))); } inline_stack_done; } /* uicb_init */ void uicb (SV *src) { int i = 0, idx = 0; STRLEN l; unsigned char *s = (unsigned char *)SvPV (src, l); while (i < l) { int n = (s[i] >> 2) & 0x3f; sv_setiv (uicb_sv[idx++], n); n = (s[i++] & 0x03) << 4; n |= (s[i] >> 4) & 0x0f; sv_setiv (uicb_sv[idx++], n); n = (s[i++] & 0x0f) << 2; n |= (s[i] >> 6) & 0x03; sv_setiv (uicb_sv[idx++], n); n = s[i++] & 0x3f; sv_setiv (uicb_sv[idx++], n); } } /* uicb */