copy_n() in _bitarray.c
=======================

The following variable names are used to in this document, as well as in
the source code:

    self    bitarray object bits are copies onto
    a       start bit (in self) bits are copied onto
    other   bitarray object bits are copied from
    b       start bit (in other) bits are copied from
    n       number of bits being copied
    p1      start byte (in self) memory is copied to, i.e. a / 8
    p2      last byte (in self) memory is copied to, i.e. (a + n - 1) / 8
    p3      first byte (in other) memory is copied from, i.e. b / 8

There are 3 cases handled by this function: (i) aligned case (ii) small n case
(iii) general case.  For all cases, it is important to handle self == other.
We will briefly discuss the first two cases, and then go into more detail
about the general case.


Aligned case
------------

In the aligned case, i.e. when both start positions (a and b) are a
multiple of 8, we use memmove() on all bytes to be copied.  This includes
any partial byte (p2), whose bits get restored afterwards.


Small n case
------------

For n smaller than 8 bits, we use a simple sequence of getbit() and setbit()
calls which is relatively slow.  However, as the general case has some
overhead, it is still faster to copy a small number of bits one by one.
As other might be self, we need to either loop forward or backwards in order
to not copy from bits already changed.


General case
------------

Here we assume that n is at least 8 bits.  We choose an aligned region to
be copied using copy_n() itself, and use shift_r8() and a few fixes to
create the correct copy.  The is done in the following steps:

1.) Calculate positions p1, p2, p3 and store the corresponding bytes from
    memory into t1, t2, t3.  We need these bytes later to restore bits which
    got overwritten or shifted away.  Note that we have to store t3 (the byte
    with b in other), as other can be self.

2.) Calculate the total right shift of bytes p1..p2 (once copied into self).
    This shift depends on a % 8 and b % 8, and has to be below 8.

3.) Using copy_n(), copy the byte region from other at p3 or p3 + 1 into
    self at p1.  Because in the latter case we miss the beginning bits in
    other, we need t3 and copy those bits later.

4.) Right shift self in byte range p1..p2.  This region includes the
    bit-range(a, a + n), but is generally larger.  This is why we need t1
    and t2 to restore the bytes at p1 and p2 in self later.

5.) Restore bits in self at, see step 4:
    - p1 using t1 (those got overwritten and shifted)
    - p2 using t2 (those got shifted)

6.) Copy the first few bits from other to self (using t3, see step 3).


Here is an example with the following parameters (created using
examples/copy_n.py):

a = 21
b = 6
n = 31
p1 = 2
p2 = 6
p3 = 0

other
bitarray('00101110 11111001 01011101 11001011 10110000 01011110 011')
b..b+n          ^^ ^^^^^^^^ ^^^^^^^^ ^^^^^^^^ ^^^^^
                   ======== ======== ======== =====
                33
self
bitarray('01011101 11100101 01110101 01011001 01110100 10001010 01111011')
a..a+n                           ^^^ ^^^^^^^^ ^^^^^^^^ ^^^^^^^^ ^^^^
                            11111
                                                                    2222
copy_n
                            ======== ======== ======== =====
bitarray('01011101 11100101 11111001 01011101 11001011 10110010 01111011')
rshift 7
                            >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>>
bitarray('01011101 11100101 00000001 11110010 10111011 10010111 01100100')
a..a+n                             = ======== ======== ======== ====
                            11111
                                                                    2222
                                 33
bitarray('01011101 11100101 01110101 11110010 10111011 10010111 01101011')
