Can SWITCH be avoided by using BIT OPERATORS or anything else ?

M

mast4as

Hi everyone

It seems that one day I saw some code where the developper managed to
use bit operations to avoid using a switch which I would like to avoid
for performance reasons. Here is what I am trying to do.

typedef float color[3];

typedef struct Test
{
float a;
float b;
color c;
float d;
};

typedef enum Type
{
TYPE_A = 1 << 0,
TYPE_B = 1 << 1,
TYPE_C = 1 << 2,
TYPE_D = 1 << 3,
};

int main( int argc, char **argv )
{
Type type = TYPE_B;
Test test;
memset( &test.a, 0x0, sizeof( Test ) );
switch ( type )
{
case TYPE_A: test.a += 1; break;
case TYPE_B: test.b -= 1; break;
case TYPE_C: test.c[ 0 ] = 1; break;
case TYPE_D: test.d += 2; break;
defaullt: ;
}
}

Basically I would like to avoid the switch statetement. What I am
trying to do in the code is add the result to the appropriate element
of the variable "test" of type Test based on the type of the variable
"type". Do you guys see a super efficient way of doing this ;-)

Many thanks -coralie
 
A

Alf P. Steinbach

* mast4as:
Hi everyone

It seems that one day I saw some code where the developper managed to
use bit operations to avoid using a switch which I would like to avoid
for performance reasons. Here is what I am trying to do.

typedef float color[3];

typedef struct Test
{
float a;
float b;
color c;
float d;
};

typedef enum Type
{
TYPE_A = 1 << 0,
TYPE_B = 1 << 1,
TYPE_C = 1 << 2,
TYPE_D = 1 << 3,
};

int main( int argc, char **argv )
{
Type type = TYPE_B;
Test test;
memset( &test.a, 0x0, sizeof( Test ) );
switch ( type )
{
case TYPE_A: test.a += 1; break;
case TYPE_B: test.b -= 1; break;
case TYPE_C: test.c[ 0 ] = 1; break;
case TYPE_D: test.d += 2; break;
defaullt: ;
}
}

Basically I would like to avoid the switch statetement. What I am
trying to do in the code is add the result to the appropriate element
of the variable "test" of type Test based on the type of the variable
"type". Do you guys see a super efficient way of doing this ;-)

Reorder your struct so that the values you're interested in are consecutive.

Represent them as an array, then use indexing.

That said, this smells very much like a kind of Evil(TM) premature optimization.
The cost of catering to this micro-efficiency can be quite high. Conversely,
much work can be saved by disregardning this level of efficiency completely,
which is what people do when they program in languages like C#, Java or Python.


Cheers & hth.


- Alf
'
 
M

mast4as

* mast4as:


Hi everyone
It seems that one day I saw some code where the developper managed to
use bit operations to avoid using a switch which I would like to avoid
for performance reasons. Here is what I am trying to do.
typedef float color[3];
typedef struct Test
{
   float a;
   float b;
   color c;
   float d;
};
typedef enum Type
{
   TYPE_A  = 1 << 0,
   TYPE_B  = 1 << 1,
   TYPE_C  = 1 << 2,
   TYPE_D  = 1 << 3,
};
int main( int argc, char **argv )
{
   Type type = TYPE_B;
   Test test;
   memset( &test.a, 0x0, sizeof( Test ) );
   switch ( type )
   {
           case TYPE_A: test.a += 1;               break;
           case TYPE_B: test.b -= 1;               break;
           case TYPE_C: test.c[ 0 ] = 1;   break;
           case TYPE_D: test.d += 2;               break;
           defaullt: ;
   }
}
Basically I would like to avoid the switch statetement. What I am
trying to do in the code is add the result to the appropriate element
of the variable "test" of type Test based on the type of the variable
"type". Do you guys see a super efficient way of doing this ;-)

Reorder your struct so that the values you're interested in are consecutive.

Represent them as an array, then use indexing.

That said, this smells very much like a kind of Evil(TM) premature optimization.
The cost of catering to this micro-efficiency can be quite high. Conversely,
much work can be saved by disregardning this level of efficiency completely,
which is what people do when they program in languages like C#, Java or Python.

Cheers & hth.

- Alf
'

Thanks a lot Alf... However saddly I don't understand what you
mean ;-) Could you please show me an example. I am happy to fix my
code but I just can't make sense of what you are saying...

You are right about the optimization but I have to do this switch
millions of time per process (and this program is runned thousands and
thousands of time ;-) which is the reason I want to be sure this is
fast ...

cheers -c
 
M

mast4as

* mast4as:
Hi everyone
It seems that one day I saw some code where the developper managed to
use bit operations to avoid using a switch which I would like to avoid
for performance reasons. Here is what I am trying to do.
typedef float color[3];
typedef struct Test
{
   float a;
   float b;
   color c;
   float d;
};
typedef enum Type
{
   TYPE_A  = 1 << 0,
   TYPE_B  = 1 << 1,
   TYPE_C  = 1 << 2,
   TYPE_D  = 1 << 3,
};
int main( int argc, char **argv )
{
   Type type = TYPE_B;
   Test test;
   memset( &test.a, 0x0, sizeof( Test ) );
   switch ( type )
   {
           case TYPE_A: test.a += 1;               break;
           case TYPE_B: test.b -= 1;               break;
           case TYPE_C: test.c[ 0 ] = 1;   break;
           case TYPE_D: test.d += 2;               break;
           defaullt: ;
   }
}
Basically I would like to avoid the switch statetement. What I am
trying to do in the code is add the result to the appropriate element
of the variable "test" of type Test based on the type of the variable
"type". Do you guys see a super efficient way of doing this ;-)
Reorder your struct so that the values you're interested in are consecutive.
Represent them as an array, then use indexing.
That said, this smells very much like a kind of Evil(TM) premature optimization.
The cost of catering to this micro-efficiency can be quite high. Conversely,
much work can be saved by disregardning this level of efficiency completely,
which is what people do when they program in languages like C#, Java or Python.
Cheers & hth.

Thanks a lot Alf... However saddly I don't understand what you
mean ;-) Could you please show me an example. I am happy to fix my
code but I just can't make sense of what you are saying...

You are right about the optimization but I have to do this switch
millions of time per process (and this program is runned thousands and
thousands of time ;-) which is the reason I want to be sure this is
fast ...

cheers -c

Howevery you know what. I ran test with this program .. SWITCH vs NO
SWITCH and the performances are similar !!!!
You are right I might not care so much about this after all ;-)

I am still interested in learning about the technique you mentionned
just for the sake of becoming a little big more knowledgeable ...
cheers

-c
 
K

Keith H Duggar

* mast4as:




Hi everyone
It seems that one day I saw some code where the developper managed to
use bit operations to avoid using a switch which I would like to avoid
for performance reasons. Here is what I am trying to do.
typedef float color[3];
typedef struct Test
{
float a;
float b;
color c;
float d;
};
typedef enum Type
{
TYPE_A = 1 << 0,
TYPE_B = 1 << 1,
TYPE_C = 1 << 2,
TYPE_D = 1 << 3,
};
int main( int argc, char **argv )
{
Type type = TYPE_B;
Test test;
memset( &test.a, 0x0, sizeof( Test ) );
switch ( type )
{
case TYPE_A: test.a += 1; break;
case TYPE_B: test.b -= 1; break;
case TYPE_C: test.c[ 0 ] = 1; break;
case TYPE_D: test.d += 2; break;
defaullt: ;
}
}
Basically I would like to avoid the switch statetement. What I am
trying to do in the code is add the result to the appropriate element
of the variable "test" of type Test based on the type of the variable
"type". Do you guys see a super efficient way of doing this ;-)

Reorder your struct so that the values you're interested in are consecutive.

Represent them as an array, then use indexing.

That said, this smells very much like a kind of Evil(TM) premature optimization.

Not only that but ... and truly mast4as I'm sorry for putting it
so bluntly ... the code as presented sucks. Maybe it is just the
obfuscated "A B C D" nomenclature but the structure and mixture
of operations (+1,-1,=1,+2) is also very suspicious to my eyes.

Anyhow, mast4as, please be aware that switch if done properly is
one of the most efficient selection structures in C++. Often the
compiler will convert switches to very efficient jump tables, or
optimized if ... else trees etc. So don't shy away from switch
for performance critical sections. They may "look" inefficient
due to the syntactic verbosity, but they compile to something
nearly optimal in many cases.

Indeed, one often considers converting if ... else and/or array
lookups, etc TO switches as part of an optimization.

KHD
 
K

Keith H Duggar

* mast4as:
Hi everyone
It seems that one day I saw some code where the developper managed to
use bit operations to avoid using a switch which I would like to avoid
for performance reasons. Here is what I am trying to do.
typedef float color[3];
typedef struct Test
{
   float a;
   float b;
   color c;
   float d;
};
typedef enum Type
{
   TYPE_A  = 1 << 0,
   TYPE_B  = 1 << 1,
   TYPE_C  = 1 << 2,
   TYPE_D  = 1 << 3,
};
int main( int argc, char **argv )
{
   Type type = TYPE_B;
   Test test;
   memset( &test.a, 0x0, sizeof( Test ) );
   switch ( type )
   {
           case TYPE_A: test.a += 1;               break;
           case TYPE_B: test.b -= 1;               break;
           case TYPE_C: test.c[ 0 ] = 1;   break;
           case TYPE_D: test.d += 2;               break;
           defaullt: ;
   }
}
Basically I would like to avoid the switch statetement. What I am
trying to do in the code is add the result to the appropriate element
of the variable "test" of type Test based on the type of the variable
"type". Do you guys see a super efficient way of doing this ;-)
Reorder your struct so that the values you're interested in are consecutive.
Represent them as an array, then use indexing.
That said, this smells very much like a kind of Evil(TM) premature optimization.
The cost of catering to this micro-efficiency can be quite high. Conversely,
much work can be saved by disregardning this level of efficiency completely,
which is what people do when they program in languages like C#, Java or Python.
Cheers & hth.
- Alf
'
Thanks a lot Alf... However saddly I don't understand what you
mean ;-) Could you please show me an example. I am happy to fix my
code but I just can't make sense of what you are saying...
You are right about the optimization but I have to do this switch
millions of time per process (and this program is runned thousands and
thousands of time ;-) which is the reason I want to be sure this is
fast ...
cheers -c

Howevery you know what. I ran test with this program .. SWITCH vs NO
SWITCH and the performances are similar !!!!
You are right I might not care so much about this after all ;-)

I am still interested in learning about the technique you mentionned
just for the sake of becoming a little big more knowledgeable ...
cheers

I think you will be very interested in this site:

http://graphics.stanford.edu/~seander/bithacks.html

However, please use with restraint and caution.

KHD
 
A

Alf P. Steinbach

* mast4as:
* mast4as:


Hi everyone
It seems that one day I saw some code where the developper managed to
use bit operations to avoid using a switch which I would like to avoid
for performance reasons. Here is what I am trying to do.
typedef float color[3];
typedef struct Test
{
float a;
float b;
color c;
float d;
};
typedef enum Type
{
TYPE_A = 1 << 0,
TYPE_B = 1 << 1,
TYPE_C = 1 << 2,
TYPE_D = 1 << 3,
};
int main( int argc, char **argv )
{
Type type = TYPE_B;
Test test;
memset( &test.a, 0x0, sizeof( Test ) );
switch ( type )
{
case TYPE_A: test.a += 1; break;
case TYPE_B: test.b -= 1; break;
case TYPE_C: test.c[ 0 ] = 1; break;
case TYPE_D: test.d += 2; break;
defaullt: ;
}
}
Basically I would like to avoid the switch statetement. What I am
trying to do in the code is add the result to the appropriate element
of the variable "test" of type Test based on the type of the variable
"type". Do you guys see a super efficient way of doing this ;-)
Reorder your struct so that the values you're interested in are consecutive.

Represent them as an array, then use indexing.

That said, this smells very much like a kind of Evil(TM) premature optimization.
The cost of catering to this micro-efficiency can be quite high. Conversely,
much work can be saved by disregardning this level of efficiency completely,
which is what people do when they program in languages like C#, Java or Python.

Cheers & hth.

- Alf
'

Thanks a lot Alf... However saddly I don't understand what you
mean ;-) Could you please show me an example. I am happy to fix my
code but I just can't make sense of what you are saying...

You are right about the optimization but I have to do this switch
millions of time per process (and this program is runned thousands and
thousands of time ;-) which is the reason I want to be sure this is
fast ...

Oh well.

Off the cuff:

class Whatever
{
private:
float myItems[6];
public:
enum Kind{ kind_a, kind_b, kind_d, kind_c };
Whatever(): myItems() {} // Zero the items
float& a() { return myItems[0]; }
float& b() { return myItems[1]; }
float& d() { return myItems[2]; }
float& c() { return myItems[3]; }
float* c_arr() { return myItems + 3; }
float& operator[]( Kind const i ) { return myItems; }
};

int main()
{
static const delta[] = { 1, 1, 2, 1 }
Whatever test;
Whatever::Kind const i = Whatever::kind_c;
test += delta;
}

Cheers & hth.,

- Alf
 
K

Keith H Duggar

Interestingly that site of yours has the following suggestion:

Compute the integer absolute value (abs) without branching
int v; // we want to find the absolute value of v
unsigned int r; // the result goes here
int const mask = v >> sizeof(int) * CHAR_BIT - 1;

Gosh, using an "unsigned int" to store an integer absolute value? Who would
have thought it. :)

Geez I didn't know ... oh wait! I actually /contributed/ to
that section:

"On March 14, 2004, Keith H. Duggar sent me the patented
variation above; it is superior to the one I initially came
up with, r=(+1|(v>>(sizeof(int)*CHAR_BIT-1)))*v, because a
multiply is not used."

PWNED ... again.

FYI there is also an /intentional/ right shift of a signed int.
I bet you think that is "wrong" just like Alf's vector reserve
hack.

Also, int r gives the exact same results and that is what I use
in my personal implementation of that hack. I must be a "use int
everywhere" troll ... who expertly uses signed AND unsigned.

KHD
 
K

Keith H Duggar

Geez I didn't know ... oh wait! I actually /contributed/ to
that section:

   "On March 14, 2004, Keith H. Duggar sent me the patented
   variation above; it is superior to the one I initially came
   up with, r=(+1|(v>>(sizeof(int)*CHAR_BIT-1)))*v, because a
   multiply is not used."

PWNED ... again.
...
Also, int r gives the exact same results and that is what I use
in my personal implementation of that hack.

I forgot to point out this is true except for v=INT_MIN on some
platforms if that edge case matters to your application.

KHD
 
M

mast4as

* mast4as:
Hi everyone
It seems that one day I saw some code where the developper managed to
use bit operations to avoid using a switch which I would like to avoid
for performance reasons. Here is what I am trying to do.
typedef float color[3];
typedef struct Test
{
   float a;
   float b;
   color c;
   float d;
};
typedef enum Type
{
   TYPE_A  = 1 << 0,
   TYPE_B  = 1 << 1,
   TYPE_C  = 1 << 2,
   TYPE_D  = 1 << 3,
};
int main( int argc, char **argv )
{
   Type type = TYPE_B;
   Test test;
   memset( &test.a, 0x0, sizeof( Test ) );
   switch ( type )
   {
           case TYPE_A: test.a += 1;               break;
           case TYPE_B: test.b -= 1;               break;
           case TYPE_C: test.c[ 0 ] = 1;   break;
           case TYPE_D: test.d += 2;               break;
           defaullt: ;
   }
}
Basically I would like to avoid the switch statetement. What I am
trying to do in the code is add the result to the appropriate element
of the variable "test" of type Test based on the type of the variable
"type". Do you guys see a super efficient way of doing this ;-)
Reorder your struct so that the values you're interested in are consecutive.
Represent them as an array, then use indexing.
That said, this smells very much like a kind of Evil(TM) premature optimization.

Not only that but ... and truly mast4as I'm sorry for putting it
so bluntly ... the code as presented sucks. Maybe it is just the
obfuscated "A B C D" nomenclature but the structure and mixture
of operations (+1,-1,=1,+2) is also very suspicious to my eyes.

Anyhow, mast4as, please be aware that switch if done properly is
one of the most efficient selection structures in C++. Often the
compiler will convert switches to very efficient jump tables, or
optimized if ... else trees etc. So don't shy away from switch
for performance critical sections. They may "look" inefficient
due to the syntactic verbosity, but they compile to something
nearly optimal in many cases.

Indeed, one often considers converting if ... else and/or array
lookups, etc TO switches as part of an optimization.

KHD

Thanks for your insight... The code is an example to illustrate what I
am trying to do...
I don't think it was a proof of how ingenious the algorithm
was ... ;-)
But many thanks for the link. I am having a look -cheers -c
 
M

mast4as

* mast4as:


* mast4as:
Hi everyone
It seems that one day I saw some code where the developper managed to
use bit operations to avoid using a switch which I would like to avoid
for performance reasons. Here is what I am trying to do.
typedef float color[3];
typedef struct Test
{
   float a;
   float b;
   color c;
   float d;
};
typedef enum Type
{
   TYPE_A  = 1 << 0,
   TYPE_B  = 1 << 1,
   TYPE_C  = 1 << 2,
   TYPE_D  = 1 << 3,
};
int main( int argc, char **argv )
{
   Type type = TYPE_B;
   Test test;
   memset( &test.a, 0x0, sizeof( Test ) );
   switch ( type )
   {
           case TYPE_A: test.a += 1;               break;
           case TYPE_B: test.b -= 1;               break;
           case TYPE_C: test.c[ 0 ] = 1;   break;
           case TYPE_D: test.d += 2;               break;
           defaullt: ;
   }
}
Basically I would like to avoid the switch statetement. What I am
trying to do in the code is add the result to the appropriate element
of the variable "test" of type Test based on the type of the variable
"type". Do you guys see a super efficient way of doing this ;-)
Reorder your struct so that the values you're interested in are consecutive.
Represent them as an array, then use indexing.
That said, this smells very much like a kind of Evil(TM) premature optimization.
The cost of catering to this micro-efficiency can be quite high. Conversely,
much work can be saved by disregardning this level of efficiency completely,
which is what people do when they program in languages like C#, Java or Python.
Cheers & hth.
- Alf
'
Thanks a lot Alf... However saddly I don't understand what you
mean ;-) Could you please show me an example. I am happy to fix my
code but I just can't make sense of what you are saying...
You are right about the optimization but I have to do this switch
millions of time per process (and this program is runned thousands and
thousands of time ;-) which is the reason I want to be sure this is
fast ...

Oh well.

Off the cuff:

   class Whatever
   {
   private:
       float myItems[6];
   public:
       enum Kind{ kind_a, kind_b, kind_d, kind_c };
       Whatever(): myItems() {}  // Zero the items
       float& a() { return myItems[0]; }
       float& b() { return myItems[1]; }
       float& d() { return myItems[2]; }
       float& c() { return myItems[3]; }
       float* c_arr() { return myItems + 3; }
       float& operator[]( Kind const i ) { return myItems; }
   };

   int main()
   {
       static const delta[] = { 1, 1, 2, 1 }
       Whatever test;
       Whatever::Kind const i = Whatever::kind_c;
       test += delta;
   }

Cheers & hth.,

- Alf


I see very nice... interesting. Thank you so much.
 
K

Keith H Duggar

Typical troll, saying someone is pwned when it is they who are in fact the
pwned. Yes I saw your name there before I posted

LMAO ... pathetic liar. We have AMPLE evidence that your ADHD and
proclivity for selection bias would have prevented you from reading
ANYTHING past "unsigned int r" before IMMEDIATELY regurgitating a
post.

You fail.

KHD
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top