shifting of bitvecs considered broken #164
Comments
From @jhiResubmitting a bug report of mine back from February; [paste] While editing my Damn Book I re-remembered that couple of months back Fiction: you have a bitvector which you want to shift. The current (5.005_03-MT5) fact: perl -wle '$b = ""; vec($b, 0, 1) = 1;print unpack("b*", $b);$b<<=1;print unpack("b*", $b)' Huh? Adding -w tells more, as usual: So left_shift assumes that the argument to shift is a number, but "^A" I consider this behaviour to be rather broken. I think $b <<= 1 should shift the whole bitvector left by one position and vec($b, 2, 8) >>= 2 should shift the bits 16..23 right by two positions (of course not Back then I asked Larry whether the current behaviour is by design or larry: I suppose << and >> ought to be made to work. There's a little more P.S. My original problem can be recoded with "use integer", but the -- Perl Info
|
From @floatingatollI can confirm this is present in @18374. |
From @schwernStill present in 5.8.5 and blead@22511 |
From @smpeters
Just so we're clear, and to add a proper TODO test case, what would you |
From @iabynOn Wed, Jul 20, 2005 at 05:56:12AM -0700, Steve Peters via RT wrote:
I am opposed to such a change in behaviour. <<= operates on numeric values, while vec operates on strings. vec($b,0,1) = 1 is just the same as $b = "\x0\x0\x0\x01" (ignoring endianess and int size complications) If the << and >> operators were to take any string as a bit pattern, then $b="1"; $b <<= 2; print $b which should print 4, not "\xc4". -- |
From @jhi
Rest peacefully, so is Larry, I once cornered him on this :-)
But on the other hand Larry could see the argumentation my way too, How to solve this, if this is to be solved? *I* see as an ugly -- |
From @jhi
How is the fixing of lexical pragmas progressing? If there were -- |
From @rgarciaOn 8/6/05, Jarkko Hietaniemi <jhietaniemi@gmail.com> wrote:
I've an unfinished patch, and I've planned to work on this after the |
From @smpeters
This thread sort of went off on a tangent. What should the expected |
From @jhiSteve Peters via RT wrote:
Well, ASSUMING that there will be in future a way to make shifting of perl -Mbitvec -wle '$b = ""; -- |
From @ysthOn Wed, Sep 28, 2005 at 09:01:12AM +0300, Jarkko Hietaniemi wrote:
I'd rather see a pragma that allowed changing how &,|, etc. work also. to allow shifting as bitvecs if they've never been used in numeric context use bitvec string => -shiftops; to have the shift ops always shift as bitvecs, and use bitvec numeric => -shiftops; being the default, making the ops always assume numbers. It would also allow affecting the bitwise ops (~, &, |, ^) which use bitvec auto => -bitwise; And would restore the defaults. I know I'd use use bitvec string => -all; often in limited lexical scopes. |
From @chipdudeHow about adding leftshift() and rightshift() as functions in a standard |
From [Unknown Contact. See original ticket]How about adding leftshift() and rightshift() as functions in a standard |
From @rgs2008/11/14 Chip Salzenberg via RT <perlbug-comment@perl.org>:
Except the obligatory bikeshedding session on the new module name, |
From @chipdudeOn Mon, Nov 17, 2008 at 09:36:07AM +0100, Rafael Garcia-Suarez wrote:
I'm having a hard time deciding which way is "left". The convention for |
From @chipdudeOn Mon, Nov 17, 2008 at 09:36:07AM +0100, Rafael Garcia-Suarez wrote:
Well ... does it count as bikeshedding if it's your own module? Here's a =item insert_low_bits STRING, COUNT Accept a bitvector STRING, a la L<vec>, and an integral bit COUNT. Return a =item remove_low_bits STRING, COUNT Accept a bitvector STRING, a la L<vec>, and an integral bit COUNT. Return a Inline Patchdiff --git a/ext/vec/Makefile.PL b/ext/vec/Makefile.PL
new file mode 100644
index 0000000..ff8910a
--- /dev/null
+++ b/ext/vec/Makefile.PL
@@ -0,0 +1,7 @@
+use ExtUtils::MakeMaker;
+
+WriteMakefile(
+ VERSION_FROM => "vec.pm",
+ NAME => "vec",
+ OPTIMIZE => '-g',
+);
diff --git a/ext/vec/t/vec.t b/ext/vec/t/vec.t
new file mode 100644
index 0000000..57a21b2
--- /dev/null
+++ b/ext/vec/t/vec.t
@@ -0,0 +1,30 @@
+#!./perl
+
+BEGIN {
+ unless (-d 'blib') {
+ chdir 't' if -d 't';
+ @INC = '../lib';
+ }
+}
+
+use Test::More tests => 15;
+use vec;
+
+ok(vec::->VERSION);
+
+ok(insert_low_bits("", 1) eq "\x00" );
+ok(insert_low_bits("", 8) eq "\x00" );
+ok(insert_low_bits("", 9) eq "\x00\x00");
+ok(insert_low_bits("\x01", 0) eq "\x01" );
+ok(insert_low_bits("\x01", 1) eq "\x02" );
+ok(insert_low_bits("\x01", 7) eq "\x80" );
+ok(insert_low_bits("\x01", 8) eq "\x00\x01");
+
+ok(remove_low_bits("", 1) eq "" );
+ok(remove_low_bits("\x01", 0) eq "\x01");
+ok(remove_low_bits("\x01", 1) eq "" );
+ok(remove_low_bits("\x00\x01", 8) eq "\x01");
+ok(remove_low_bits("\x00\x01", 9) eq "" );
+ok(remove_low_bits("\x80", 7) eq "\x01");
+ok(remove_low_bits("\x00\x80", 15) eq "\x01");
+
diff --git a/ext/vec/vec.pm b/ext/vec/vec.pm
new file mode 100644
index 0000000..1f6e06c
--- /dev/null
+++ b/ext/vec/vec.pm
@@ -0,0 +1,69 @@
+# vec.pm
+#
+# Copyright (c) 2008 Chip Salzenberg <chip@pobox.com>. All rights reserved.
+# This program is free software; you can redistribute it and/or modify it
+# under the same terms as Perl itself.
+
+package vec;
+
+use strict;
+
+require Exporter;
+
+our $VERSION = 0.01;
+our $XS_VERSION = $VERSION;
+our @ISA = qw(Exporter);
+our @EXPORT = qw(insert_low_bits remove_low_bits);
+our @EXPORT_OK = @EXPORT;
+
+require XSLoader;
+XSLoader::load('vec', $XS_VERSION);
+
+1;
+
+__END__
+
+=head1 vec
+
+vec - Bit-vector functions not provided by the base language
+
+=head1 SYNOPSIS
+
+ use vec qw(insert_low_bits remove_low_bits);
+ use vec; # same as above
+
+=head1 DESCRIPTION
+
+The C<vec> module provides some bit vector functionality that perhaps could
+have been part of the base language, but aren't, and for reasons of backward
+compatibility now cannot be.
+
+=over 4
+
+=item insert_low_bits STRING, COUNT
+
+Accept a bitvector STRING, a la L<vec>, and an integral bit COUNT. Return a
+new bitvector that is a copy of the original STRING but with COUNT zero bits
+inserted at the low end of the vector; that is, at the front of the string.
+COUNT must be nonnegative.
+
+=item remove_low_bits STRING, COUNT
+
+Accept a bitvector STRING, a la L<vec>, and an integral bit COUNT. Return a
+new bitvector that is a copy of the original STRING but with COUNT bits
+removed from the low end of the vector; that is, from the front of the
+string.
+
+=back
+
+=head1 SEE ALSO
+
+L<vec>
+
+=head1 COPYRIGHT
+
+Copyright (c) 2008 Chip Salzenberg <chip@pobox.com>. All rights reserved.
+This program is free software; you can redistribute it and/or modify it
+under the same terms as Perl itself.
+
+=cut
diff --git a/ext/vec/vec.xs b/ext/vec/vec.xs
new file mode 100644
index 0000000..41d45e8
--- /dev/null
+++ b/ext/vec/vec.xs
@@ -0,0 +1,83 @@
+/* Copyright (c) 2008 Graham Barr <chip@pobox.com>. All rights reserved.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the same terms as Perl itself.
+ */
+
+#include <EXTERN.h>
+#include <perl.h>
+#include <XSUB.h>
+
+MODULE=vec PACKAGE=vec
+
+PROTOTYPES: DISABLE
+
+SV *
+insert_low_bits(ssv, shift)
+ SV * ssv
+ IV shift
+ PREINIT:
+ size_t len;
+ const char * const s = SvPV_const(ssv, len);
+ UV ibytes, ibits, iextra;
+ char *d;
+ CODE:
+ if (shift < 0)
+ croak("invalid left shift");
+ ibytes = shift >> 3;
+ ibits = shift & 7;
+ iextra = ibits && (!len || ((unsigned char)s[len - 1] >> (8 - ibits)));
+ RETVAL = newSV(len + ibytes + iextra + 1);
+ d = SvPVX(RETVAL);
+ Zero(d, ibytes, char);
+ d += ibytes;
+ if (!ibits) {
+ Copy(s, d, len, char);
+ d += len;
+ }
+ else {
+ size_t i;
+ *d++ = (unsigned char)s[0] << ibits;
+ for (i = 1; i < len + iextra; ++i)
+ *d++ = ((unsigned char)s[i ] << ibits ) |
+ ((unsigned char)s[i-1] >> (8 - ibits));
+ }
+ *d = '\0';
+ SvCUR_set(RETVAL, d - SvPVX_const(RETVAL));
+ SvPOK_on(RETVAL);
+ OUTPUT:
+ RETVAL
+
+SV *
+remove_low_bits(ssv, shift)
+ SV * ssv
+ IV shift
+ PREINIT:
+ size_t len;
+ const char * const s = SvPV_const(ssv, len);
+ UV rbytes, rbits, rextra;
+ char *d;
+ CODE:
+ if (shift < 0)
+ croak("invalid left shift");
+ rbytes = shift >> 3;
+ rbits = shift & 7;
+ rextra = rbits && len && !((unsigned char)s[len - 1] >> rbits);
+ if (len <= rbytes + rextra)
+ XSRETURN_PVN("", 0);
+ RETVAL = newSV(len - (rbytes + rextra) + 1);
+ d = SvPVX(RETVAL);
+ if (!rbits) {
+ Copy(s + rbytes, d, len - rbytes, char);
+ d += len - rbytes;
+ }
+ else {
+ size_t i;
+ for (i = rbytes; i < len - rextra; ++i)
+ *d++ = ((unsigned char)s[i ] >> rbits ) |
+ ((unsigned char)s[i+1] << (8 - rbits));
+ }
+ *d = '\0';
+ SvCUR_set(RETVAL, d - SvPVX_const(RETVAL));
+ SvPOK_on(RETVAL);
+ OUTPUT:
+ RETVAL
-- Chip Salzenberg <chip@pobox.com> |
From @rgs2008/11/17 Chip Salzenberg <chip@pobox.com>:
I expect this one will need to be dual-lived. At which point occurs the Some minor nits:
à la L<perlfunc/vec>
What about "shift" and "unshift" instead of insert and remove ?
Add to that C<MAN3PODS => {}> (to avoid converting the manpage needlessly)
Maybe add some tests with strings flagged as utf8 ? Just to be sure it
You're Graham Barr in disguise ? :) |
From ben@morrow.me.ukQuoth chip@pobox.com (Chip Salzenberg):
"shiftdown" and "shiftup"? Although, given that it only works on Ben |
From @timbunceOn Mon, Nov 17, 2008 at 03:21:29AM -0800, Chip Salzenberg wrote:
The function name makes me think I can supply the bits that will be Instead of focussing on just these two shift operations I wonder if an splicebits VEC,OFFSET,LENGTH,LIST subbits VEC,OFFSET,LENGTH,REPLACEMENT With more specialized functions implemented, or at least specified, in Just a thought. Tim. |
From perl@profvince.com
I concur. When I was writing Scalar::Vec::Util, I felt like the atomic Vincent. |
From @nwc10On Mon, Nov 17, 2008 at 12:43:39PM +0100, Rafael Garcia-Suarez wrote:
Yes, this was my thought too. If it exists, and it's not the default, and you Nicholas Clark |
From @chipdudeOn Mon, Nov 17, 2008 at 02:27:17PM +0100, Vincent Pit wrote:
Your Calar::Vec::Util::vcopy method ... does it work with overlapping |
From @chipdudeOn Mon, Nov 17, 2008 at 01:31:11PM +0000, Nicholas Clark wrote:
I agree. Since the original reporter was Jarkko, and he asked for a language |
From @chipdudeOn Mon, Nov 17, 2008 at 09:04:12AM -0800, Chip Salzenberg wrote:
Silly me, RTFM: vcopy $t, 10, $t, 20, 30; # Overalapping areas DWIM. OK, I'm calling the bug closed. Thanks, Vincent. |
@chipdude - Status changed from 'open' to 'resolved' |
Migrated from rt.perl.org#969 (status was 'resolved')
Searchable as RT969$
The text was updated successfully, but these errors were encountered: