Go Down

### Topic: bitSet only sets bits from 0 to 31 (previously to 15) (Read 8290 times)previous topic - next topic

#### local_dani_21

##### Nov 11, 2013, 08:14 pmLast Edit: Nov 14, 2013, 12:35 pm by local_dani_21 Reason: 1
Hi

I just realised that bitSet() only works for bits 0 to 31. When wanting to set bits higher than 31, I seem to have to use bitWrite(); Is this an error or a wanted behaviour?

Regards,
Dani

Code: [Select]
`uint64_t sternbilder = 0;bitSet(sternbilder, 8); // for bits from 0 to 31bitWrite(sternbilder, 32, 1); // for bits 32 and above`

#### robtillaart

#1
##### Nov 11, 2013, 08:46 pm

From Arduino.h

#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))

so bitWrite() is just a call to bitSet()

because  it use   1UL   which is essentially  32bit unsigned it will not work for uint64_t

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

#### Jantje

#2
##### Nov 11, 2013, 08:46 pm
The code for bitSet is a macro which looks  long compatible to me.
Also bitWrite is a macro using bitSet.
So if bitWrite works for longs; bitSet should as well

Code: [Select]
`#define bitSet(value, bit) ((value) |= (1UL << (bit)))#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))`

Best regards
Jantje
Do not PM me a question unless you are prepared to pay for consultancy.
Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -

#### robtillaart

#3
##### Nov 11, 2013, 09:05 pmLast Edit: Nov 11, 2013, 09:19 pm by robtillaart Reason: 1
A solution for 64bit values is to define the following macros, as they use explicit an unsigned long long as datatype.
(you include these in the Arduino.h )

Code: [Select]
`#define bitSet64(value, bit) ((value) |= (1ULL << (bit)))#define bitClear64(value, bit) ((value) &= ~(1ULL << (bit)))#define bitWrite64(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))`
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

#### robtillaart

#4
##### Nov 11, 2013, 09:16 pm

A more elaborate solution might be
Code: [Select]
`////    FILE: .ino//  AUTHOR: Rob Tillaart// VERSION: 0.1.00// PURPOSE: //    DATE: //     URL://// Released to the public domain//#define bitSet64(value, bit) ((value) |= (bit<32?1UL:1ULL) <<(bit))#define bitClear64(value, bit) ((value) &= ~(bit<32?1UL:1ULL) <<(bit))#define bitWrite64(value, bit, bitvalue) (bitvalue ? bitSet64(value, bit) : bitClear64(value, bit))void setup() {  Serial.begin(115200);  Serial.println("Start ");  uint64_t sternbilder = 0;  for (int i=1; i<65; i*=2)  {    bitSet64(sternbilder, i-1);   }  Serial.println(sternbilder, BIN);}void loop() {}`

Note: I have patched Print.h for uint64 - http://forum.arduino.cc/index.php?topic=143584.msg1079973#msg1079973 -
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

#### Jantje

#5
##### Nov 11, 2013, 09:22 pm
Rob
The existing macros should work for unsigned long, right?
That is from bit 16 to 31
Your proposal is needed for bits 32 to 63
Or did I miss something?
Best regards
Jantje
Do not PM me a question unless you are prepared to pay for consultancy.
Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -

#### local_dani_21

#6
##### Nov 11, 2013, 09:47 pm
Rob, you are so fast I'm hardly able to type in your suggestions before you have an even better one I patched the Print.h und Print.cpp and included your #definitions for 64bit magic an am very happy that now everything works as expected. Thank you very much - you should add this code to future arduino-IDE-releases!

#### local_dani_21

#7
##### Nov 11, 2013, 09:50 pm
Jantje, I think you are right - I think I have gotten the 15 wrong - it seems to be 31 that is the limit with the normal bitSet()-function. Please excuse my misswriting. Dani.

#### Jantje

#8
##### Nov 11, 2013, 09:51 pm
Dani
Thanks; I started thinking I was loosing it
Best regards
Jantje
Do not PM me a question unless you are prepared to pay for consultancy.
Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -

#### local_dani_21

#9
##### Nov 11, 2013, 09:56 pm
Jantje, you were perfectly present!

#### robtillaart

#10
##### Nov 11, 2013, 10:10 pm
It is better to test the sizeof(value) than to test bit,  as bit often bit can be a variable so its value cannot be checked compile time.

Code: [Select]
`#define bitSet64(value, bit) ((value) |= (sizeof(value)<5?1UL:1ULL) <<(bit))#define bitClear64(value, bit) ((value) &= ~(sizeof(value)<5?1UL:1ULL) <<(bit))#define bitWrite64(value, bit, bitvalue) (bitvalue ? bitSet64(value, bit) : bitClear64(value, bit))`

posted as issue - https://github.com/arduino/Arduino/issues/1670 -
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

#### kowalski

#11
##### Nov 11, 2013, 11:11 pmLast Edit: Nov 12, 2013, 11:25 am by kowalski Reason: 1
C++ allows us to do things beyond macros. How about a template class for any size bitset? With operator syntax and that is adapted for an 8-bit machine as ATmega328.
Code: [Select]
`template<uint16_t N>class bitset_t {private:  uint8_t m_set[(N + 4)/CHARBITS];public:  bitset_t()  {    empty();  }  uint16_t members()  {    return (N);  }  void empty()  {    memset(m_set, 0, sizeof(m_set));  }  bool operator[](uint16_t ix)  {    if (ix < N)      return ((m_set[ix / CHARBITS] & _BV(ix & (CHARBITS - 1))) != 0);    return (false);  }  void operator+=(uint16_t ix)  {    if (ix < N) m_set[ix / CHARBITS] |= _BV(ix & (CHARBITS - 1));  }  void operator-=(uint16_t ix)  {    if (ix < N) m_set[ix / CHARBITS] &= ~_BV(ix & (CHARBITS - 1));  }  void dump()  {    for (uint16_t i = 0; i < N; i++)      printf("%d", (m_set[i / CHARBITS] & _BV(i & (CHARBITS - 1))) != 0);    printf("\n");  }};`

A small test program (as tested on Linux).

Code: [Select]
`enum {  GREEN,  BLUE,  YELLOW,  RED};  int main(){  bitset_t<48> b;  TRACE(b[GREEN]);  b += GREEN;  TRACE(b[GREEN]);  b -= GREEN;  TRACE(b[GREEN]);  b += RED;  b.dump();  b += YELLOW;  b.dump();  b += 47;  b.dump();  b += 48;  b.dump();  b += 100;  b.dump();  return (0);}`

This is the output:

Code: [Select]
`b[GREEN] = 0b[GREEN] = 1b[GREEN] = 0000100000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000001100000000000000000000000000000000000000000001001100000000000000000000000000000000000000000001001100000000000000000000000000000000000000000001`

Cheers!

#### Jantje

#12
##### Nov 11, 2013, 11:18 pm
Dani
Maybe it is a good idea to change the title of the first post. 15->31
Best regards
Jantje
Do not PM me a question unless you are prepared to pay for consultancy.
Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -

#### robtillaart

#13
##### Nov 12, 2013, 05:52 pm

After some testing it became clear that  changing 1UL into 1ULL is enough to support 64 bit. without affecting 32 bit performance.

#define bitSet64(value, bit) ((value) |= (1ULL << (bit )) )
#define bitClear64(value, bit) ((value) &= ~(1ULL <<(bit)))

more about tests,  see - https://github.com/arduino/Arduino/issues/1670 -

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

#### local_dani_21

#14
##### Nov 14, 2013, 12:38 pm

Dani
Maybe it is a good idea to change the title of the first post. 15->31
Best regards
Jantje

I did - hope it helps others.
Thanks again,
Dani

Go Up