Powerbasic Museum 2020-B

IT-Consultant: Patrice Terrier => Discussion => Topic started by: Patrice Terrier on March 17, 2013, 07:31:07 PM

Title: C++ <bitset> and PB's BIT function/statement
Post by: Patrice Terrier on March 17, 2013, 07:31:07 PM
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 ?

...
Title: Re: C++ <bitset> and PB's BIT function/statement
Post by: Theo Gottwald on March 18, 2013, 09:14:21 AM
I think it can be done using ASM.
However then its not more easily convertible to x64.
Title: Re: C++ <bitset> and PB's BIT function/statement
Post by: Patrice Terrier on March 18, 2013, 10:51:06 AM
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.
Title: Re: C++ <bitset> and PB's BIT function/statement
Post by: Patrice Terrier on March 18, 2013, 11:37:38 AM
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)) );
}
Title: Re: C++ <bitset> and PB's BIT function/statement
Post by: Charles Pegge on March 18, 2013, 11:57:01 AM
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
Title: Re: C++ <bitset> and PB's BIT function/statement
Post by: Patrice Terrier on March 18, 2013, 11:57:41 AM
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) );
}
Title: Re: C++ <bitset> and PB's BIT function/statement
Post by: Charles Pegge on March 18, 2013, 12:16:31 PM

Beware modulo and division are deadly slow! :)
Title: Re: C++ <bitset> and PB's BIT function/statement
Post by: Patrice Terrier on March 18, 2013, 12:24:37 PM
Charles

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

...
Title: Re: C++ <bitset> and PB's BIT function/statement
Post by: Charles Pegge on March 18, 2013, 12:37:44 PM

You can use an int cast to override different types

char c[] ...
 BitReset((int*)&c[ i ],1);
Title: Re: C++ <bitset> and PB's BIT function/statement
Post by: Charles Pegge on March 18, 2013, 01:29:49 PM
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;
  }
Title: Re: C++ <bitset> and PB's BIT function/statement
Post by: Patrice Terrier on March 18, 2013, 01:45:10 PM
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.

...

Title: Re: C++ <bitset> and PB's BIT function/statement
Post by: Patrice Terrier on March 18, 2013, 02:19:02 PM
Charles

The macro version doesn't work, at least with VS2010, using long array and LONG_PTR.
Title: Re: C++ <bitset> and PB's BIT function/statement
Post by: Charles Pegge on March 18, 2013, 02:41:32 PM
They should work with any type as they do in gcc, including arrays.

Do we need extra brackets to enforce precedence?
Title: Re: C++ <bitset> and PB's BIT function/statement
Post by: Patrice Terrier on March 18, 2013, 05:01:47 PM
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.
Title: Re: C++ <bitset> and PB's BIT function/statement
Post by: Charles Pegge on March 18, 2013, 06:49:07 PM
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]
Title: Re: C++ <bitset> and PB's BIT function/statement
Post by: Patrice Terrier on March 18, 2013, 08:54:01 PM
Charles

Thanks for the tip!

...