I have an 2-byte string, an I wish to extract the numeric value of its 4 nybbles into an array. Below I have 5 working variations, but they are all quite complex and quite slow.
print map{hex} (split'', unpack 'h4', $n)[2,3,0,1]; #! Gives >> 15 0 0 15 print map{ ( ord($_) & 0xf0 ) >> 4, ord($_) & 0x0f } split//, $n; #! Gives >> 15 0 0 15 print map{ vec $n, $_, 4 } 0 .. 3; #! Gives >> 0 15 15 0 print +(map{ vec $n, $_, 4 } 0 .. 3)[2,3,0,1]; #! Gives >> 15 0 0 15 print map{ ( unpack( 'n' , $n ) >> ( 4 * $_ ) ) & 0xf } 0 .. 3; #! Gives >> 15 0 0 15 $n = unpack 'n', $n; print map{ ($n >>( 4 * $_ )) & 0xf } 0 .. 3; #! Gives >> 15 0 0 15
There has to be a better way?
Code and benchmark
#! perl -slw use strict; use Benchmark qw[cmpthese]; our $n = "\xf0\x0f"; print unpack 'hhhh', $n; #! Gives >> 0 f print unpack 'h h h h', $n; #! Gives >> 0 f print unpack 'h2 h2', $n; #! Gives >> 0f f0 +# two 2-byte strings print unpack 'h4', $n; #! Gives >> 0ff0 # + a single 4 char string print map{hex} (split'', unpack 'h4', $n)[2,3,0,1]; #! + Gives >> 15 0 0 15 print map{ ( ord($_) & 0xf0 ) >> 4, ord($_) & 0x0f } split//, $n; #! + Gives >> 15 0 0 15 print map{ vec $n, $_, 4 } 0 .. 3; #! + Gives >> 0 15 15 0 print +(map{ vec $n, $_, 4 } 0 .. 3)[2,3,0,1]; #! + Gives >> 15 0 0 15 print map{ ( unpack( 'n' , $n ) >> ( 4 * $_ ) ) & 0xf } 0 .. 3; #! + Gives >> 15 0 0 15 $n = unpack 'n', $n; print map{ ($n >>( 4 * $_ )) & 0xf } 0 .. 3; #! + Gives >> 15 0 0 15 our @nybbles = (); cmpthese( -1, { #! 1 map, 4 hexes (Just my luck!), a split, an unpack, a list and +a slice. map_hex_split_unpack => q[ @nybbles = map{hex} (split'', unpack 'h4', $n)[2,3,0,1]; ], #! 1 map, 2 ords, 2 ands, shift right 4, 1 split and a partridge i +n a pair tree! map_ord_and_shift_split => q[ @nybbles = map{ ( ord($_) & 0xf0 ) >> 4, ord($_) & 0x0f } sp +lit//, $n; ], #! 1 map, 4 vecs, two lists, one splice. Phew! map_vec_lists_splice => q[ @nybbles = map{ ( unpack( 'n' , $n ) >> ( 4 * $_ ) ) & 0xf } + 0 .. 3; ], #! 1map, 4 X ( unpack, shift, mult, & ), a list #! and enough brackets to keep a LISP afficianardo happy for days. map_unpack_shift_mult_and_list => q[ @nybbles = map{ ( unpack( 'n' , $n ) >> ( 4 * $_ ) ) & 0xf } + 0 .. 3; ], #! Factor out the unpack. Slightly better. unpack_map_shift_and_list => q[ $n = unpack 'n', $n; @nybbles = map{ ( $n >> ( 4 * $_ ) ) & +0xf } 0 .. 3; ], }); __DATA__ C:\test>test map_hex_split_unpack: 1 wallclock secs @ 10317.66/s (n=107 +51) map_ord_and_shift_split: 1 wallclock secs @ 7324.69/s (n= 76 +25) map_unpack_shift_mult_and_list: 2 wallclock secs @ 12869.53/s (n=146 +97) map_vec_lists_splice: 1 wallclock secs @ 12954.41/s (n=133 +56) unpack_map_shift_and_list: 1 wallclock secs @ 15328.34/s (n=153 +59) Rate MOASP MHSU MUSMUL MVLS +UMSL map_ord_and_shift_split 7325/s -- -29% -43% -43% +-52% map_hex_split_unpack 10318/s 41% -- -20% 20% +-33% map_unpack_shift_mult_and_list 12870/s 76% 25% -- -1% +-16% map_vec_lists_splice 12954/s 77% 26% 1% -- +-15% unpack_map_shift_and_list 15328/s 109% 49% 19% 18% + -- C:\test>
In anyone has/or can produce a Inline C or XS equivalent built for AS 633 or AS 802, I'd sell my soul er... be very grateful>
Examine what is said, not who speaks.
The 7th Rule of perl club is -- pearl clubs are easily damaged. Use a diamond club instead.
In reply to Nybbles take to long by BrowserUk
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |