@@ -94,6 +94,8 @@ static PyTypeObject Bitarraytype;
9494#define GETBIT (self , i ) \
9595 ((self)->ob_item[(i) / 8] & BITMASK((self)->endian, i) ? 1 : 0)
9696
97+ #define ckb (i ) assert(!(((i) < 0) || ((i) >= Py_SIZE(res))))
98+
9799static void
98100setbit (bitarrayobject * self , idx_t i , int bit )
99101{
@@ -270,8 +272,10 @@ delete_n(bitarrayobject *self, idx_t start, idx_t n)
270272 assert (0 <= n && n <= self -> nbits - start );
271273 if (n == 0 )
272274 return 0 ;
273-
274- copy_n (self , start , self , start + n , self -> nbits - start - n );
275+ if (start != self -> nbits + 1 ) {
276+ /* default pop() wihtout index, in that case no copying is needed */
277+ copy_n (self , start , self , start + n , self -> nbits - start - n );
278+ }
275279 return resize (self , self -> nbits - n );
276280}
277281
@@ -371,6 +375,7 @@ bitwise(bitarrayobject *self, PyObject *arg, enum op_type oper)
371375 return 0 ;
372376}
373377
378+
374379/* set the bits from start to stop (excluding) in self to val */
375380static void
376381setrange (bitarrayobject * self , idx_t start , idx_t stop , int val )
@@ -1780,6 +1785,7 @@ bitarray_pop(bitarrayobject *self, PyObject *args)
17801785 return NULL ;
17811786 }
17821787 vi = GETBIT (self , i );
1788+
17831789 if (delete_n (self , i , 1 ) < 0 )
17841790 return NULL ;
17851791 return PyBool_FromLong (vi );
@@ -2376,6 +2382,150 @@ searchiter_dealloc(searchiterobject *it)
23762382 PyObject_GC_Del (it );
23772383}
23782384
2385+ static PyObject *
2386+ bitarray_lshift (bitarrayobject * self , PyObject * other )
2387+ {
2388+ if (self -> endian != 1 ) {
2389+ PyErr_SetString (PyExc_ValueError , "Only implemented for bigendian." );
2390+ return NULL ;
2391+ }
2392+
2393+ if (!IS_INDEX (other )) {
2394+ PyErr_SetString (PyExc_TypeError , "integer argument to lshift expected" );
2395+ return NULL ;
2396+ }
2397+ idx_t count = 0 ;
2398+ getIndex (other , & count );
2399+
2400+ bitarrayobject * res = (bitarrayobject * )bitarray_copy (self );
2401+
2402+ Py_ssize_t i ;
2403+
2404+ /* too much */
2405+ if (count > res -> nbits ) {
2406+ memset (res -> ob_item , 0 , Py_SIZE (res ));
2407+
2408+ } else if (count > 0 ) {
2409+ Py_ssize_t bytes = count / 8 ;
2410+
2411+ /* move bytes around first */
2412+ if (bytes > 0 ) {
2413+ for (i = 0 ; (i + bytes ) < Py_SIZE (res ); i ++ ) {
2414+ ckb (i );
2415+ ckb (i + bytes );
2416+ res -> ob_item [i ] = res -> ob_item [i + bytes ];
2417+ }
2418+
2419+ /* clear bytes on the right */
2420+ for (i = 0 ; i < bytes ; i ++ ) {
2421+ ckb (Py_SIZE (res ) - 1 - i );
2422+ res -> ob_item [Py_SIZE (res ) - 1 - i ] = 0 ;
2423+ }
2424+
2425+ }
2426+
2427+ /* perform shift smaller than 8 */
2428+ idx_t small_shift = count % 8 ;
2429+ if (small_shift > 0 ) {
2430+ for (i = 0 ; i < Py_SIZE (res ) - bytes ; i ++ ) {
2431+ ckb (i );
2432+ res -> ob_item [i ] <<= small_shift ;
2433+
2434+ if ((i + 1 ) < Py_SIZE (res )) {
2435+ ckb (i );
2436+ ckb (i + 1 );
2437+ res -> ob_item [i ] |= (unsigned char )((unsigned char )(res -> ob_item [i + 1 ]) >> (8 - small_shift ));
2438+ }
2439+ }
2440+ }
2441+
2442+ /* clear right edge */
2443+ idx_t border_bit = (res -> nbits - count ) % 8 ;
2444+ idx_t border_byte = (res -> nbits - count ) / 8 ;
2445+ ckb (border_byte );
2446+ res -> ob_item [border_byte ] &= (unsigned char )(0xff << (8 - border_bit ));
2447+ if (border_byte + 1 < Py_SIZE (res )) {
2448+ ckb (border_byte + 1 );
2449+ res -> ob_item [border_byte + 1 ] = 0 ;
2450+ }
2451+
2452+ }
2453+ return (PyObject * )res ;
2454+ }
2455+ PyDoc_STRVAR (lshift_doc ,
2456+ "lshift([i]) -> item\n\
2457+ \n\
2458+ Shifts all bits i positions to the left and returns a new bitarray.\n\
2459+ It works only on bigendian machines." );
2460+
2461+
2462+ static PyObject *
2463+ bitarray_rshift (bitarrayobject * self , PyObject * other )
2464+ {
2465+ if (self -> endian != 1 ) {
2466+ PyErr_SetString (PyExc_ValueError , "Only implemented for bigendian." );
2467+ return NULL ;
2468+ }
2469+ if (!IS_INDEX (other )) {
2470+ PyErr_SetString (PyExc_TypeError , "integer argument to rshift expected" );
2471+ return NULL ;
2472+ }
2473+ idx_t count = 0 ;
2474+ getIndex (other , & count );
2475+
2476+ bitarrayobject * res = (bitarrayobject * )bitarray_copy (self );
2477+
2478+ idx_t i ;
2479+
2480+ /* too much */
2481+ if (count > res -> nbits ) {
2482+ memset (res -> ob_item , 0 , Py_SIZE (res ));
2483+
2484+ } else if (count > 0 ) {
2485+ idx_t bytes = count / 8 ;
2486+
2487+ /* move bytes around first */
2488+ if (bytes > 0 ) {
2489+ for (i = Py_SIZE (res ) - 1 ; i >= bytes ; i -- ) {
2490+ ckb (i );
2491+ ckb (i - bytes );
2492+ res -> ob_item [i ] = res -> ob_item [i - bytes ];
2493+ }
2494+
2495+ /* clear bytes on the right */
2496+ for (i = 0 ; i < bytes ; i ++ ) {
2497+ ckb (i );
2498+ res -> ob_item [i ] = 0 ;
2499+ }
2500+
2501+ }
2502+
2503+ /* perform shift smaller than 8 */
2504+ idx_t small_shift = count % 8 ;
2505+ if (small_shift > 0 ) {
2506+ for (i = Py_SIZE (res ) - 1 ; i >= bytes ; i -- ) {
2507+ ckb (i );
2508+ res -> ob_item [i ] = ((unsigned char )res -> ob_item [i ]) >> small_shift ;
2509+
2510+ if (i >= 1 ) {
2511+ ckb (i - 1 );
2512+ unsigned char from_left = ((unsigned char )(res -> ob_item [i - 1 ]) << (8 - small_shift ));
2513+ ckb (i );
2514+ res -> ob_item [i ] |= from_left ;
2515+ }
2516+ }
2517+ }
2518+ }
2519+
2520+ return (PyObject * )res ;
2521+ }
2522+ PyDoc_STRVAR (rshift_doc ,
2523+ "rshift([i]) -> item\n\
2524+ \n\
2525+ Shifts all bits i positions to the right and returns a new bitarray.\n\
2526+ It works only on bigendian machines." );
2527+
2528+
23792529static int
23802530searchiter_traverse (searchiterobject * it , visitproc visit , void * arg )
23812531{
@@ -2466,6 +2616,10 @@ bitarray_methods[] = {
24662616 pack_doc },
24672617 {"pop" , (PyCFunction ) bitarray_pop , METH_VARARGS ,
24682618 pop_doc },
2619+ {"lshift" , (PyCFunction ) bitarray_lshift , METH_O ,
2620+ lshift_doc },
2621+ {"rshift" , (PyCFunction ) bitarray_rshift , METH_O ,
2622+ rshift_doc },
24692623 {"remove" , (PyCFunction ) bitarray_remove , METH_O ,
24702624 remove_doc },
24712625 {"reverse" , (PyCFunction ) bitarray_reverse , METH_NOARGS ,
0 commit comments