+ if ($bits < $length) {
+ $length -= $bits;
+ if ($left) {
+ vcopy($_[0], $start, $_[0], $start + $bits, $length);
+ vfill($_[0], $start, $bits, $insert) if defined $insert;
+ } else {
+ vcopy($_[0], $start + $bits, $_[0], $start, $length);
+ vfill($_[0], $start + $length, $bits, $insert) if defined $insert;
+ }
+ } else {
+ vfill($_[0], $start, $length, $insert) if defined $insert;
+ }
+}
+
+=head2 C<vrot>
+
+ vrot $v, $start, $length, $bits;
+
+In the area starting at C<$start> and of length C<$length> in C<$v>, rotates bits C<abs $bits> positions left if C<< $bits > 0 >> and right otherwise.
+
+C<$v> is upgraded to a string if it isn't one already.
+If C<$start + $length> goes out of the bounds of C<$v>, then the extra bits are treated as zeros.
+Bits that are outside of the specified area are left untouched.
+
+This function currently allocates an extra buffer of size C<O($bits)>.
+
+=cut
+
+sub vrot ($$$$) {
+ my ($start, $length, $bits) = @_[1 .. 3];
+ return unless $length and $bits;
+ croak 'Invalid negative offset' if $start < 0;
+ croak 'Invalid negative length' if $length < 0;
+ my $left = 1;
+ if ($bits < 0) {
+ $left = 0;
+ $bits = -$bits;
+ }
+ $bits %= $length;
+ return unless $bits;