[comp.unix.questions] bit mover

handeli@ocfmail.ocf.llnl.gov (03/14/91)

I need a C function which can move arbitrary
bits around from one memory location to another
with a bit offset of anything. For example,
the call might look like

movebits(a1,ioff1,a2,ioff2,nbits)

where a1 and a2 are char arrays
ioff1 and ioff2 are bit offsets into the
char arrays
nbits is the number of bits to move.
a1 might be source address and a2 might be
destination address.

Anybody have such a function?

bharat@cf-cm.computing-maths.cardiff.ac.uk (Bharat Mediratta) (03/14/91)

In article <788@llnl.LLNL.GOV> handeli@ocfmail.ocf.llnl.gov () writes:
>I need a C function which can move arbitrary
>bits around from one memory location to another
>with a bit offset of anything. For example,
>the call might look like
>
>movebits(a1,ioff1,a2,ioff2,nbits)
>
>where a1 and a2 are char arrays
>ioff1 and ioff2 are bit offsets into the
>char arrays
>nbits is the number of bits to move.
>a1 might be source address and a2 might be
>destination address.
>
>Anybody have such a function?


DISCLAIMER: I haven't tested this, but I think it will work.

/* 
 * Off1 & Off2 are the offsets of the bit 
 * 0 = rightmost bit.
 * No error correction
 */     
movebits(src, off1, dest, off2, nbits)
int *src, *dest;
int off1, off2, nbits;
{
        off1 = 1<<off1; 
        off2 = 1<<off2; 
        while (nbits--) 
        {
		*dest &= ~off2; /* Zero out the location */
		*dest |= ((*src & off1)? 0xFFFF : 0x0000) & off2;  /* Yuk */
                off2 <<=1; 
                off1 <<=1;
        }
}

Cheers!

 -Bharat 
--
|  Bharat Mediratta  | JANET: bharat@cm.cf.ac.uk                               |
+--------------------+ UUNET: bharat%cm.cf.ac.uk%cunyvm.cuny.edu@uunet.uucp    |
|On a clear disk...  | uk.co: bharat%cm.cf.ac.uk%cunyvm.cuny.edu%uunet.uucp@ukc|
|you can seek forever| UUCP: ...!uunet!cunym.cuny.edu!cm.cf.ac.uk!bharat       |

mouse@thunder.mcrcim.mcgill.edu (der Mouse) (03/15/91)

In article <788@llnl.LLNL.GOV>, handeli@ocfmail.ocf.llnl.gov writes:
> I need a C function which can move arbitrary bits around from one
> memory location to another with a bit offset of anything.  For
> example, the call might look like

> movebits(a1,ioff1,a2,ioff2,nbits)

This really belongs in a C group.  I have cross-posted to comp.lang.c
and am redirecting followups there.

I am assuming that the bits in a byte are taken LSB-first, so that an
offset of 9, for example, skips the first byte and the LSB of the
second byte.  To switch this, fiddle with some of the shift operations.

Warning: untested.  Assumes that the number of bits in an unsigned int
is no less than one less than twice the number of bits in an unsigned
char (most machines will have no trouble with this restraint).
Optimization possibilities abound.

#define CHAR_BITS 8 /* or whatever: # of bits in unsigned char */

movebits(a1,ioff1,a2,ioff2,nbits)
unsigned char *a1; /* from */
unsigned int ioff1;
unsigned char *a2; /* to */
unsigned int ioff2;
unsigned int nbits;
{
 unsigned int buf;
 unsigned char mask;
 int have;

 if (nbits < 1) return; /* careful: don't read *a1 in this case */
 a1 += ioff1 / CHAR_BITS;
 ioff1 %= CHAR_BITS;
 a2 += ioff2 / CHAR_BITS;
 ioff2 %= CHAR_BITS;
 buf = *a1++;
 have = CHAR_BITS - ioff1;
 buf >>= ioff1;
 while (nbits > 0)
  { if ((have < CHAR_BITS) && (nbits > have))
     { buf |= *a1++ << have;
       have += CHAR_BITS;
     }
    if (ioff2+nbits < CHAR_BITS)
     { mask = ((1 << nbits) - 1) << ioff2;
     }
    else
     { mask = (~0) << ioff2;
     }
    *a2 = (*a2 & ~mask) | ((buf << ioff2) & mask);
    a2 ++;
    buf >>= CHAR_BITS - ioff2;
    have -= CHAR_BITS - ioff2;
    nbits -= CHAR_BITS - ioff2;
    ioff2 = 0;
  }
}

					der Mouse

			old: mcgill-vision!mouse
			new: mouse@larry.mcrcim.mcgill.edu