GIDForums  

Go Back   GIDForums > Computer Programming Forums > C Programming Language
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

 
 
Thread Tools Search this Thread Rate Thread
  #1  
Old 23-Sep-2006, 12:16
mikhail mikhail is offline
Junior Member
 
Join Date: Mar 2004
Location: Dublin, Ireland
Posts: 73
mikhail is on a distinguished road

Convert 'one hot' to integer


Hi all, I've a tricky little question for you.

A friend of mine is trying to do some optimisation, and he has one operation that he does again and again. If he could speed it up, it'd help no end.

He is storing a number of the form 2^a as an integer, and he wants to get the a as quickly as possible. So, in binary, he might have:
2^3 (0000000000001000)
so he wants the integer 3 from that. He's happy to consider a hardware solution or anything.

What he's doing right now, AFAIK, is a check on each half (not sure of the detail), iterated until he's down to one location. Is there anything faster?
  #2  
Old 23-Sep-2006, 12:36
LuciWiz's Avatar
LuciWiz LuciWiz is offline
Moderator
 
Join Date: Jul 2004
Location: Cluj-Napoca (Romania)
Posts: 890
LuciWiz is a jewel in the roughLuciWiz is a jewel in the roughLuciWiz is a jewel in the roughLuciWiz is a jewel in the rough

Re: Convert 'one hot' to integer


Some time ago, a link to this very neat page was posted in a thread on the forums. I suggest you try the "// OR (IF YOU KNOW v IS A POWER OF 2)" example. I think I figured out how it works

Best regards,
Lucian
__________________
Please read these Guidelines before posting on the forum

"A person who never made a mistake never tried anything new."
Einstein
  #3  
Old 23-Sep-2006, 17:10
mikhail mikhail is offline
Junior Member
 
Join Date: Mar 2004
Location: Dublin, Ireland
Posts: 73
mikhail is on a distinguished road

Re: Convert 'one hot' to integer


Thanks, but that's the complexity (O(log(n))) he has already. I suspect that there isn't a faster way TBH.
  #4  
Old 23-Sep-2006, 20:48
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 4,693
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold

Re: Convert 'one hot' to integer


Quote:
Originally Posted by mikhail
Thanks, but that's the complexity (O(log(n))) he has already. I suspect that there isn't a faster way TBH.

If you have a 32-bit one-hot number and you want to know the position of the 1, then the output will be a number greater than or equal to zero and less than or equal to 31 (a five-bit number). I assume here that a 1 in the least significant position will yield a value of zero, and a 1 in the most signficant position will yield a value of 31 decimal (0x1f hex).

Your friend is probably determining each bit independently. This can be done (easily) if you allow each bit decision to consist of a single logical operation and comparison. Since there are five bits in the result, there will be five decisions. (Is this what you mean by (O(log(n))? SInce log of 32 to the base 2 is five, this may be the ultimate for this kind of problem). Since it's easy to do 32-bit operations with built-in operators and data types, a C program is kind of trivial (and short). See footnote.

An equivalent combinatorial hardware impelementation could consist of five 32-input and gates; logic inverters may be necessary for each of the 32 input bits, depending on the exact nature of the gates. Conceptually simple, and easy to do in an FPGA or PLD, but low-cost devices usually don't have enough pins (32 inputs, 5 outputs, power, ground).

Hardware and software solutions may require a bit more logic to implement some kind of "data valid" output that is desirable in general just in case it is presented with an invalid input--- That is: no bits set or more than one bit set in the input word. (A little pun, get it? A "bit" more logic? No? Oh, well...)

There are more complex structures that consider more than one bit at a time

For example, consider a Read-Only Memory that has 32 address bits and five data output bits. Consider that you have defined the ROM contents so that the data value for address 0x00000001 is 0, the data value for 0x00000002 is 1, the data value for address 0x00000004 is 3, ..., the data value for adress 0x80000000 is 32 decimal (0x1f hex). And all other locations are zero.

Of course this requires a 4 gigaword 5-bit memory to hold the 32 relevant outputs. Probably not practical unless speed is the only consideration (and price is no object). It can be done combinatorially and the propagation delay is dependent on the technology. Custom large ROMs for such a simple application seems like a large amount of overkill, but, hey, it's your money.

Then, there are Content-Addressable Memory elements (CAMs) that are used in network routers and other places where you store a "key" value at a given address, then you can do a "reverse lookup" by giving the key value and the CAM will give you the address.

So you store key value 0x00000001 in address 1
store key value 0x00000002 in address 2
store key value 0x00000004 in address 3
.
.
.
store key value0x80000000 in address 32

You only need 32 entries in the CAM, compared with over 4 billion for the ROM.


Now if you apply a value of 0x02000000, the CAM gives you 25. (Indicating that bit number 25 is set).

Error detection is automatic, since any illegal input will not have had a key value stored, and the CAM will give a "no joy" output.

You may be able to find a commercial device, or you may be able to design a FPGA or PLD to implement it in hardware.

Again, there may be quite a bit of logic in the design, but it can give you your result in a single clock cycle (they are usually implemented in a way that requires a clock, and clock speed depends on the technology, obviously). Still pretty pricey for a simple application like this, but, a possibility if price is no object.

Regards,

Dave

Footnote: For the following example, I could have put all of the bit operations into a single C statement, but I separated them for purposes of illustration. If you don't see how it works, then print out the results at each step. Note that since speed is supposedly important, I didn't try to do something elegant like making a loop with a cleverly designed way of creating a bit mask or any such thing. Of course for maximum speed, I would have made it an in-line function (or, even, a macro) with a single statement.

Left As An Exercise For The Interested Reader: How would you put in error detection? What would be the impact on program size and run time? Would you still be able to implement it with a macro or an in-line function, given that it has two return values? (Or could you just define an extra output bit that holds the "valid" condition?)

I know that GNU gcc has the C99 Standard defined <inttypes.h> that I use to make sure the input will be a 32-bit number. Most compilers these days have 32-bit ints (and they don't seem to have <inttypes.h>), so I put in a test to make sure --- at least it works for me with Borland and Microsoft compilers to which I have access. Of course, for a given compiler, once you have verified the size of whatever data type you have, you can leave out the assertion stuff, but I kind of like having it there just in case I absent-mindedly try to port stuff like this to development environments with limited capabilities (besides creaky old Borland TurboC, lots of compilers for small microcontrollers have 16-bit ints).

CPP / C++ / C Code:

/*
 * implementation of a one-hot encoder for a 32-bit number (No error checking.)
 * ---davekw7x
 */
#include <stdio.h>

#ifdef __GNUC__
#include <inttypes.h>
#else
#include <assert.h>
typedef unsigned int uint32_t;
#endif

int main()
{
    int encode(uint32_t indata);
    uint32_t one_hot_data;

#ifndef __GNUC__
    if (sizeof(uint32_t) < 4) {
        printf("The program won't work unless sizeof(unsigned int) >= 4\n");
        assert(sizeof(uint32_t) >= 4);
    }
#endif

    for (one_hot_data = 0x80000000; one_hot_data; one_hot_data >>= 1) {
        printf("0x%08x ==> %2d\n", one_hot_data, encode(one_hot_data));
    }
    return 0;
}

int encode(uint32_t indata)
{
    int retval;

    retval =  ((0xffff0000 & indata) != 0) ? 0x10 : 0;
    retval |= ((0xff00ff00 & indata) != 0) ? 0x08 : 0;
    retval |= ((0xf0f0f0f0 & indata) != 0) ? 0x04 : 0;
    retval |= ((0xcccccccc & indata) != 0) ? 0x02 : 0;
    retval |= ((0xaaaaaaaa & indata) != 0) ? 0x01 : 0;

    return retval;
}

Output
Code:
0x80000000 ==> 31 0x40000000 ==> 30 0x20000000 ==> 29 0x10000000 ==> 28 0x08000000 ==> 27 0x04000000 ==> 26 0x02000000 ==> 25 0x01000000 ==> 24 0x00800000 ==> 23 0x00400000 ==> 22 0x00200000 ==> 21 0x00100000 ==> 20 0x00080000 ==> 19 0x00040000 ==> 18 0x00020000 ==> 17 0x00010000 ==> 16 0x00008000 ==> 15 0x00004000 ==> 14 0x00002000 ==> 13 0x00001000 ==> 12 0x00000800 ==> 11 0x00000400 ==> 10 0x00000200 ==> 9 0x00000100 ==> 8 0x00000080 ==> 7 0x00000040 ==> 6 0x00000020 ==> 5 0x00000010 ==> 4 0x00000008 ==> 3 0x00000004 ==> 2 0x00000002 ==> 1 0x00000001 ==> 0
Last edited by davekw7x : 23-Sep-2006 at 21:30.
  #5  
Old 24-Sep-2006, 07:44
mikhail mikhail is offline
Junior Member
 
Join Date: Mar 2004
Location: Dublin, Ireland
Posts: 73
mikhail is on a distinguished road

Re: Convert 'one hot' to integer


Wow, thanks Dave. The CAM solution looks interesting.

Yeah, by O(log(n)) I meant 5 clock cycles here.
 
 

Recent GIDBlogWelcome to Baghdad by crystalattice

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
A program to convert miles to kilometres Persian_Devil13 C Programming Language 23 03-Feb-2006 22:57
how to make a 'INTEGER to BINARY' code? justaHSstudent C++ Forum 1 02-Oct-2005 14:22
convert char to integer blah C++ Forum 40 18-Aug-2005 14:08
Convert Integer to String soldier C Programming Language 5 18-Aug-2005 09:11
Problem on sin(C programming) fwongmc C Programming Language 8 10-Dec-2004 10:08

Network Sites: GIDNetwork · GIDWebHosts · GIDSearch · Learning Journal by J de Silva, The

All times are GMT -6. The time now is 14:48.


vBulletin, Copyright © 2000 - 2008, Jelsoft Enterprises Ltd.