• Welcome to Powerbasic Museum 2020-B.
 

News:

Forum in repository mode. No new members allowed.

Main Menu

C++ <bitset> and PB's BIT function/statement

Started by Patrice Terrier, March 17, 2013, 07:31:07 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Patrice Terrier

I did try the c++ <bitset> class to replace the  PB's BIT function/statement,
but C++ doesn't serve the same purpose, because you can't set/reset a specific bit within any array type.

Do you know a C/C++ code that does exactly the same than PB ?

...
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Theo Gottwald

I think it can be done using ASM.
However then its not more easily convertible to x64.

Patrice Terrier

I know in essence how to do it, but my limited knowledge of the C/C++ syntax for bit manipulation is what i must master first.
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Patrice Terrier

#3
Here is one that should work with bits stored in a long array. (sorry for the cryptic C/C++ syntax)  :-X

void BitSet(IN long data[], IN long b) {
   data[b / 32] |= (1 << (b % 32));
}

void BitReSet(IN long data[], IN long b) {
   data[b / 32] &= ~(1 << (b % 32));
}

bool BitGet(IN long data[], IN long b) {
   return ( data[b / 32] & (1 << (b % 32)) );
}
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Charles Pegge

#4
Hi Patrice,

Interesting question - I hardly ever use bits but here is my best effort: This will support arrays. I use a pointer for the number parameter in all the calls.

Code (c) Select


  /* bit testing and setting example */

  #include <stdio.h>

  int Bit(int *n,int i)
  {
   if ((*n & 1<<i)==0) return 0; else return 1;
  }

  void BitSet(int *n,int i)
  {
   *n |= 1<<i;
  }


  void BitReset(int *n,int i)
  {
   int b=~(1<<i);
   *n &=b;
  }

  void BitToggle(int *n,int i)
  {
   int b=1<<i;
   *n ^=b;
  }


  int main ()
  {
  //tests
  int m[]={0x5,0xd,0x15};
  int i=1;
  printf ("%i\n", Bit(&m[i],1));
  BitSet(&m[i],1);
  printf ("%i\n", Bit(&m[i],1));
  BitReset(&m[i],1);
  printf ("%i\n", Bit(&m[i],1));
  BitToggle(&m[i],1);
  printf ("%i\n", Bit(&m[i],1));
  BitToggle(&m[i],1);
  printf ("%i\n", Bit(&m[i],1));
  printf ("%x\n", m[i]);
  return 0;
  }



Charles

Patrice Terrier

Perhaps less cryptic with the use of a macro.

#define BitMask(b) (1 << (b % 32))

void BitSet(IN long data[], IN long b) {
   data[b / 32] |= BitMask(b);
}

void BitReSet(IN long data[], IN long b) {
   data[b / 32] &= ~BitMask(b);
}

bool BitGet(IN long data[], IN long b) {
   return ( data[b / 32] & BitMask(b) );
}
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Charles Pegge


Beware modulo and division are deadly slow! :)

Patrice Terrier

Charles

How would you set / reset a bit in a char array with yours?
(i mean how to call the Bitset)

...
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Charles Pegge


You can use an int cast to override different types

char c[] ...
BitReset((int*)&c[ i ],1);

Charles Pegge

#9
Patrice,

I think my use of casts with chars could cause problems, due to the mask potentially operating over the char boundary.

Your idea of using macros is safer and cleaner, (though the macros turn out incomprehensible :) )

/* bit testing and setting using macros */

  #include <stdio.h>

  #define Bit(a,n,i) if ((n & 1<<i)==0) a=0; else a=1
  #define BitSet(n,i) n |=(1<<i)
  #define BitReset(n,i) n &=(~(1<<i))
  #define BitToggle(n,i) n ^=(1<<i)

  int main ()
  {
  //tests
  int m[]={0x5,0xd,0x15};
  char c[100]="@EF";
  int b=1;
  int a;
  Bit(a,m[1],b);
  printf ("%x\n", a);
  Bit(a,c[1],b);
  printf ("%x\n", a);
  BitToggle(c[1],b);
  printf ("%x\n", c[1]);
  BitToggle(c[1],b);
  printf ("%x\n", c[1]);
  return 0;
  }

Patrice Terrier

Charles

Yep, macro could be the way to go, because the code must work in both 32/64-bit.
The previous example you posted would work only in 32-bit, because we need to use LONG_PTR instead of int.

Testing your macro version right now on 64-bit.

...

Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Patrice Terrier

#11
Charles

The macro version doesn't work, at least with VS2010, using long array and LONG_PTR.
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Charles Pegge

They should work with any type as they do in gcc, including arrays.

Do we need extra brackets to enforce precedence?

Patrice Terrier

#13
Charles

Here is exaclty what i want to do:

#include "stdafx.h"
#include <windows.h>   // Search along the path.
#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;

#define MyBitTest(Var, Pos) ((Var) & (1 << (Pos)))

#define BitMask(BitPos) (1 << (BitPos % 32))
#define UsingLongArray(ArrayName) (LONG_PTR*) &ArrayName[0]

void BitSet(IN LONG_PTR *data, IN long BitPos) {
    data[BitPos >> 5] |= BitMask(BitPos);
}

bool BitGet(IN LONG_PTR *data, IN long BitPos) {
    return ( data[BitPos >> 5] & BitMask(BitPos) );
}

void BitReset(IN LONG_PTR *data, IN long BitPos) {
    data[BitPos >> 5] &= ~BitMask(BitPos);
}

int _tmain(int argc, _TCHAR* argv[])
{

    long data[8] = {0};
    // Set bit 13
    BitSet(UsingLongArray(data), 13);
    wcout << "set bit 13 = " << BitGet(UsingLongArray(data), 13) << endl;

    // Reset bit 13
    BitReset(UsingLongArray(data), 13);
    wcout << "reset bit 13 = " << BitGet(UsingLongArray(data), 13) << endl;

    wcout << endl;
    system("pause");  // Halts execution; shows the "Press any key to continue..." prompt

    return 0;
}


It works exactly like PB with an array of LONG.
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Charles Pegge

data[BitPos / 32]

This should give you better performance: The shift instruction is 30x faster than division. (the compiler might do this for you aleady if it is optimising)

data[BitPos >>5]