Multiply two integers without using any arithmetic operators - c

I've managed to add and subtract two integers without using any arithmetic operators. I've tried multiply ways to multiply two integers together but can't seem to make any progress. How can I multiply two integers without using any arithmetic operators? The arithemtic operators you can't use are (+, ++, +=, -, --, -=, ∗, /, %). Also from the directions that were given is to "take lowest 16 bits of the product should be
stored in product, and the full product should be stored in full_product as a 32-bit value." The commented out lines in the method are there to show you what not to do. Thanks! Here is the code done in C
#include "alu.h"
/* Adds the two arguments and stores the sum in the return structure's result
* field. If the operation overflowed then the overflow flag is set. */
addition_subtraction_result add(uint16_t augend, uint16_t addend) {
addition_subtraction_result addition;
while (addend != 0){
int carry = augend & addend;
augend = augend ^ addend;
addend = carry << 1;
}
addition.result = augend;
//addition.overflow = false;
return addition;
}
/* Subtracts the second argument from the first, stores the difference in the
* return structure's result field. If the operation overflowed then the
* overflow flag is set. */
addition_subtraction_result subtract(uint16_t menuend, uint16_t subtrahend) {
addition_subtraction_result subtraction;
while (subtrahend != 0 ){
int borrow = (~menuend) & subtrahend;
menuend = menuend ^ subtrahend;
subtrahend = borrow << 1;
}
subtraction.result = menuend;
return subtraction;
}
/* Multiplies the two arguments. The function stores lowest 16 bits of the
* product in the return structure's product field and the full 32-bit product
* in the full_product field. If the product doesn't fit in the 16-bit
* product field then the overflow flag is set. */
multiplication_result multiply(uint16_t multiplicand, uint16_t multiplier) {
multiplication_result multiplication;
//multiplication.product = multiplicand * multiplier; // THIS IS DISALLOWED
//multiplication.full_product = multiplicand * multiplier; // THIS IS DISALLOWED
multiplication.product = multiplicand;
multiplication.full_product = multiplicand;
return multiplication;
}

General idea (types are deliberately incorrect to you can't copy/paste this back in):
uint16_t multiply(uint8_t multiplicand, uint8_t multiplier)
{
uint16_t result = 0;
for (int i = 0; i < CHAR_BIT * sizeof(multiplier); i++)
if (multiplier & (uint8_t))
result = add(result, (uint16_t)multiplicand << (uint16_t)i);
return result;
}
But this won't work for you yet because because you don't have long add yet. We need to decompose long add like this:
uint16_t addlong(uint8_t addend1a, uint8_t addend1b, uint8_t addend2a, uint8_t addend2b)
{
struct addend_result a = add(addend1a, addend2a);
struct addend_result b = add(addend2a, addend2b);
if (a.carry) b = add(b.result, 1);
return a.result | ((uint16_t)b.result << 8);
}
So these are the pieces required to build. Adapt them to the framework you actually have and the type widths you actually have.
You have to unroll the for loop in multiply because of silliness. This means you get 16 lines because your input size is 16 bits.

Related

Combining four 16bit numbers into single 64bit number

I need to combine four numbers in hex format into single number. The first option that I thought of was to do left shift by n*16 (n=0,1,2,3..) for each number.
This works fine when the numbers are 0xABCD.
If a number is 0x000A, the leading zeroes are ignored and whole thing stops working (not performs as expected).
I need to have all the leading zeroes because I have to know the position of 1's in the 64bit number.
user.profiles is a 64bit value where the each part of tmp_arr is shifted to the left and stored. Am I missing something here? Or am I just going crazy?
for(int i = 0; i < 4; i++)
{
EE_ReadVariable(EE_PROFILES_1 + i, &tmp_arr[i]); // increment the address by i (D1->D2->D3->D4)
user.profiles |= (tmp_arr[i] << (i*16)); // shift the value by multiples of 16 to get 64bit number
}
C allows type-punning using unions, so you could have something like this:
union value_union
{
uint16_t v16[4];
uint64_t v64;
};
// ...
union value_union values;
values.v16[0] = value1;
values.v16[1] = value2;
values.v16[2] = value3;
values.v16[3] = value4;
printf("64-bit value = 0x%016"PRIx64"\n", values.v64);
In order to write embedded C, it is very important that you know of Implicit type promotion rules.
tmp_arr[i] << (i*16) on a 32 bit system like STM32 promotes the tmp_arr[i] argument to 32 bit signed int. This comes with two complications:
If you happen to shift a value into the sign bit of this 32 bit int, you get an undefined behavior bug.
If you shift beyond the size of this 32 bit int, you get an undefined behavior bug (and data shifted out is lost.
You need to use 64 bit unsigned arithmetic for this (which will be fairly inefficient on a 32 bitter):
user.profiles |= (uint64_t)tmp_arr[i] << i*16;
The size and type of what's on the left side of the assignment operator is completely irrelevant here.
Also, when coding for embedded systems get rid of sloppy int and the other "primitive" default types, use the types of stdint.h only. In the average embedded system, you rarely ever want any signed types, they just create problems. For STM32, you'll want to use uint32_t in most cases.
As I mentioned in the comments, you need to cast your uint16_t temporary to uint64_t before shifting up and you should check for errors.
The "missing" leading zeroes probably comes from using the wrong format for printf.
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
uint64_t get_profiles() {
uint64_t rv = 0;
uint16_t tmp;
for(int i = 0; i < 4; i++) {
uint16_t res = EE_ReadVariable(EE_PROFILES_1 + i, &tmp);
switch(res) {
case 0: rv |= (uint64_t)tmp << i*16; break;
case 1: /* variable not found */ break; // deal with error
case NO_VALID_PAGE: /* no valid page found */ break; // deal with error
}
}
return rv;
}
int main () {
// ...
user.profiles = get_profiles();
printf("%016" PRIx64 "\n", user.profiles); // prints leading zeroes
}
You can avoid casting and the need to force intermediate 64-bit arithmetic by shifting the target and masking into the least significant 16 bits in two separate implicitly 64 bit operations, thus:
user.profiles = 0u ;
for(int i = 0; i < 4; i++)
{
EE_ReadVariable( EE_PROFILES_1 + i, &tmp_arr[i] ) ;
user.profiles <<= 16 ;
user.profiles |= tmp_arr[i] ;
}
In the shift-assignment and the OR-assignment, the right-hand operand it is implicitly promoted the same type as the right hand.
If tmp_arr is not used then:
user.profiles = 0u ;
for(int i = 0; i < 4; i++)
{
uint16_t tmp = 0 ;
EE_ReadVariable( EE_PROFILES_1 + i, &tmp ) ;
user.profiles <<= 16 ;
user.profiles |= tmp ;
}

create your own my128int data type with the help of inbuilt c data type

I want to create my own data type which can hold values from -2^127 to 2^127-1 and want to perform addition on two my128int data type variable.
I search on stackoverflow community and found custom data type in C
What additional task is required from the above discussed thread.
void addition(my128int a, my128int b)
{
....
//perform some task
// print the result a+b
}
For an integer data type, I don't much care for the solution offered in the (unaccepted) answer to the question you referenced.
Myself, I would implement a type such as you describe like this:
typedef struct myint128_s {
uint32_t bits[4];
} myint128;
Addition would then look like this:
void myint128_add(myint128 *addend1, myint128 *addend2, myint128 *sum) {
uint32_t carry = 0;
int i;
for (i = 0; i < 4; i += 1) {
uint64_t temp = (uint64_t) addend1->bits[i]
+ (uint64_t) addend2->bits[i] + carry;
sum->bits[i] = (uint32_t) temp;
carry = (uint32_t) (temp >> 32);
}
/* can detect overflow here, if desired */
}
This assumes / provides a twos complement representation of negative numbers, consistent with the bounds you specified for representable numbers. You don't then have to give any special attention to the sign bit (bit 63 of bits[3]).
In effect, this is a numeric representation in base 2^32.

Implementing BigInteger

I need to implement a 1024bit math operations in C .I Implemented a simple BigInteger library where the integer is stored as an array "typedef INT UINT1024[400]" where each element represent one digit. It turned up to be so slow so i decided to implement the BigInteger using a 1024bit array of UINT64: "typedef UINT64 UINT1024[16]"
so for example the number : 1000 is represented as {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000},
18446744073709551615 as {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xFFFFFFFFFFFFFFFF} and 18446744073709551616 as {0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}.
I started wih writing the function to convert a char array number to an UINT1024 and an UINT1024 to a char array, it worked with numbers <= 0xFFFFFFFFFFFFFFFF.
Here's what i did:
void UINT1024_FROMSTRING(UIN1024 Integer,const char szInteger[],UINT Length) {
int c = 15;
UINT64 Result = 0,Operation,Carry = 0;
UINT64 Temp = 1;
while(Length--)
{
Operation = (szInteger[Length] - '0') * Temp;
Result += Operation + Carry;
/*Overflow ?*/
if (Result < Operation || Temp == 1000000000000000000)
{
Carry = Result - Operation;
Result = 0;
Integer[c--] = 0;
Temp = 1;
}
else Carry = 0;
Temp *= 10;
}
if (Result || Carry)
{
/* I DONT KNOW WHAT TO DO HERE ! */
}
while(c--) Integer[c] = 0;}
So please how can i implement it and is it possible to implement it using UINT64 for speed or just to stick with each array element is a digit of the number which is very slow for 1024bit operations.
PS: I can't use any existing library !
Thanks in advance !
Update
Still can't figure out how to do the multiplication. I am using this function:
void _uint128_mul(UINT64 u,UINT64 v,UINT64 * ui64Hi,UINT64 * ui64Lo)
{
UINT64 ulo, uhi, vlo, vhi, k, t;
UINT64 wlo, whi, wt;
uhi = u >> 32;
ulo = u & 0xFFFFFFFF;
vhi = v >> 32;
vlo = v & 0xFFFFFFFF;
t = ulo*vlo; wlo = t & 0xFFFFFFFF;
k = t >> 32;
t = uhi*vlo + k;
whi = t & 0xFFFFFFFF;
wt = t >> 32;
t = ulo*vhi + whi;
k = t >> 32;
*ui64Lo = (t << 32) + wlo;
*ui64Hi = uhi*vhi + wt + k;
}
Then
void multiply(uint1024_t dUInteger,uint1024_t UInteger)
{
int i = 16;
UINT64 lo,hi,Carry = 0;
while(i--)
{
_uint128_mul(dUInteger[i],UInteger[15],&hi,&lo);
dUInteger[i] = lo + Carry;
Carry = hi;
}
}
I really need some help in this and Thanks in advance !
You need to implement two functions for your UINT1024 class, multiply by integer and add integer. Then for each digit you convert, multiply the previous value by 10 and add the value of the digit.
Writing, debugging, defining test cases, and checking they do work right is a huge undertaking. Just get one of the packaged multiprecission arithmetic libraries, like GMP, perhaps though NTL or CLN for C++. There are other alternatives, trawl the web. Jôrg Arndt's Matters Computational gives source code for C++.
If you are doing this for your education, you should take the middle road between your two previous approaches. Put more than 1 bit into a leaf or digit, but do not use the full bit range of the integer type.
The reason is that this may significantly simplify the multiplication operation if you can at first just accumulate the products a[i]*b[j] in c[i+j]. And then normalize the result to the fixed digit range. c has length 2N-1, and this should fit into 1024 bit, so a and b are restricted to 512 bit.
If the arrays a and b hold N digits with maximum value B-1, B=2^b, then the largest of the c[k] is c[N-1] with bound N*(B-1)^2. Thus the design constraints are
(2N)*b>=1024
ld(N)+(2b)<=64
b N 2N*b ld(N)+2b
32 16 1024 68
24 22 1056 53
28 19 1064 61
So one possibility is to set b=28, B=1<
Even more suited for educational purposes would be to set B=10^d, e.g. with d=9, so that conversion from and to string is relatively trivial.

What is the fastest way for calculating the sum of arbitrary large binary numbers

I can't seem to find any good literature about this. Having a BigBinaryNumber (two's complement with virtual sign bit) structure like this:
typedef unsigned char byte;
enum Sign {NEGATIVE = (-1), ZERO = 0, POSITIVE = 1};
typedef enum Sign Sign;
struct BigBinaryNumber
{
byte *number;
Sign signum;
unsigned int size;
};
typedef struct BigBinaryNumber BigBinaryNumber;
I could just go for the elementary school approach (i.e. summing individual bytes and using the carry for subsequent summing) or perhaps work with a fixed size look-up table.
Is there any good literature about the fastest method for binary summation?
The fastest method for adding numbers is your processor's existing add instruction. So long as you've got the number laid out sensibly in memory (e.g, you don't have the bit order backwards or anything), it should be pretty straightforward to load 32 bits at a time from each number, add them together natively, and get the carry:
uint32_t *word_1 = &number1.number + offset, *word_2 = &number2.number + offset;
uint32_t *word_tgt = &dest.number + offset;
uint64_t sum = *word_1 + *word_2 + carry; // note the type!
*word_tgt = (uint32_t) sum; // truncate
carry = sum >> 32;
Note that you might have to add some special cases for dealing with the last byte in the number (or make sure that *number always has a multiple of 4 bytes allocated).
If you're using a 64-bit CPU, you may be able to extend this to work with uint64_t. There's no uint128_t for the overflow, though, so you might have to use some trickery to get the carry bit.
The "trick" is to use the native (or maybe larger) integer size.
#duskwuff is on the money to walk through number, multiple bytes at a time.
As with all "What is the fastest way ...", candidate solutions should be profiled.
Follows is a one type solution so one could use the largest type as well, the native type or any 1 type. e.g. uintmax_t or unsigned. The carry is partiality handled via code and carry generation depends on testing if addition will overflow.
typedef unsigned MyInt;
#define MyInt_MAX UINT_MAX
void Add(BigBinaryNumber *a, BigBinaryNumber *b, BigBinaryNumber *sum) {
// Assume same size for a, b, sum.
// Assume memory allocated for sum.
// Assume a->size is a multiple of sizeof(MyInt);
// Assume a->number endian is little and matches platform endian.
// Assume a->alignment matches MyInt alignment.
unsigned int size = a->size;
MyInt* ap = a->number;
MyInt* bp = b->number;
MyInt* sump = sum->number;
int carry = 0;
while (size > 0) {
size -= sizeof(MyInt);
if (carry) {
if (*ap <= (MyInt_MAX - 1 - *bp)) {
carry = 0;
}
*sump++ = *ap++ + *bp++ + 1;
}
else {
if (*ap > (MyInt_MAX - *bp)) {
carry = 1;
}
*sump++ = *ap++ + *bp++;
}
} // end while
// Integer overflow/underflow handling not shown,
// but depend on carry, and the sign of a, b
// Two's complement sign considerations not shown.
}

Bit reversal of an integer, ignoring integer size and endianness

Given an integer typedef:
typedef unsigned int TYPE;
or
typedef unsigned long TYPE;
I have the following code to reverse the bits of an integer:
TYPE max_bit= (TYPE)-1;
void reverse_int_setup()
{
TYPE bits= (TYPE)max_bit;
while (bits <<= 1)
max_bit= bits;
}
TYPE reverse_int(TYPE arg)
{
TYPE bit_setter= 1, bit_tester= max_bit, result= 0;
for (result= 0; bit_tester; bit_tester>>= 1, bit_setter<<= 1)
if (arg & bit_tester)
result|= bit_setter;
return result;
}
One just needs first to run reverse_int_setup(), which stores an integer with the highest bit turned on, then any call to reverse_int(arg) returns arg with its bits reversed (to be used as a key to a binary tree, taken from an increasing counter, but that's more or less irrelevant).
Is there a platform-agnostic way to have in compile-time the correct value for max_int after the call to reverse_int_setup(); Otherwise, is there an algorithm you consider better/leaner than the one I have for reverse_int()?
Thanks.
#include<stdio.h>
#include<limits.h>
#define TYPE_BITS sizeof(TYPE)*CHAR_BIT
typedef unsigned long TYPE;
TYPE reverser(TYPE n)
{
TYPE nrev = 0, i, bit1, bit2;
int count;
for(i = 0; i < TYPE_BITS; i += 2)
{
/*In each iteration, we swap one bit on the 'right half'
of the number with another on the left half*/
count = TYPE_BITS - i - 1; /*this is used to find how many positions
to the left (and right) we gotta move
the bits in this iteration*/
bit1 = n & (1<<(i/2)); /*Extract 'right half' bit*/
bit1 <<= count; /*Shift it to where it belongs*/
bit2 = n & 1<<((i/2) + count); /*Find the 'left half' bit*/
bit2 >>= count; /*Place that bit in bit1's original position*/
nrev |= bit1; /*Now add the bits to the reversal result*/
nrev |= bit2;
}
return nrev;
}
int main()
{
TYPE n = 6;
printf("%lu", reverser(n));
return 0;
}
This time I've used the 'number of bits' idea from TK, but made it somewhat more portable by not assuming a byte contains 8 bits and instead using the CHAR_BIT macro. The code is more efficient now (with the inner for loop removed). I hope the code is also slightly less cryptic this time. :)
The need for using count is that the number of positions by which we have to shift a bit varies in each iteration - we have to move the rightmost bit by 31 positions (assuming 32 bit number), the second rightmost bit by 29 positions and so on. Hence count must decrease with each iteration as i increases.
Hope that bit of info proves helpful in understanding the code...
The following program serves to demonstrate a leaner algorithm for reversing bits, which can be easily extended to handle 64bit numbers.
#include <stdio.h>
#include <stdint.h>
int main(int argc, char**argv)
{
int32_t x;
if ( argc != 2 )
{
printf("Usage: %s hexadecimal\n", argv[0]);
return 1;
}
sscanf(argv[1],"%x", &x);
/* swap every neigbouring bit */
x = (x&0xAAAAAAAA)>>1 | (x&0x55555555)<<1;
/* swap every 2 neighbouring bits */
x = (x&0xCCCCCCCC)>>2 | (x&0x33333333)<<2;
/* swap every 4 neighbouring bits */
x = (x&0xF0F0F0F0)>>4 | (x&0x0F0F0F0F)<<4;
/* swap every 8 neighbouring bits */
x = (x&0xFF00FF00)>>8 | (x&0x00FF00FF)<<8;
/* and so forth, for say, 32 bit int */
x = (x&0xFFFF0000)>>16 | (x&0x0000FFFF)<<16;
printf("0x%x\n",x);
return 0;
}
This code should not contain errors, and was tested using 0x12345678 to produce 0x1e6a2c48 which is the correct answer.
typedef unsigned long TYPE;
TYPE reverser(TYPE n)
{
TYPE k = 1, nrev = 0, i, nrevbit1, nrevbit2;
int count;
for(i = 0; !i || (1 << i && (1 << i) != 1); i+=2)
{
/*In each iteration, we swap one bit
on the 'right half' of the number with another
on the left half*/
k = 1<<i; /*this is used to find how many positions
to the left (or right, for the other bit)
we gotta move the bits in this iteration*/
count = 0;
while(k << 1 && k << 1 != 1)
{
k <<= 1;
count++;
}
nrevbit1 = n & (1<<(i/2));
nrevbit1 <<= count;
nrevbit2 = n & 1<<((i/2) + count);
nrevbit2 >>= count;
nrev |= nrevbit1;
nrev |= nrevbit2;
}
return nrev;
}
This works fine in gcc under Windows, but I'm not sure if it's completely platform independent. A few places of concern are:
the condition in the for loop - it assumes that when you left shift 1 beyond the leftmost bit, you get either a 0 with the 1 'falling out' (what I'd expect and what good old Turbo C gives iirc), or the 1 circles around and you get a 1 (what seems to be gcc's behaviour).
the condition in the inner while loop: see above. But there's a strange thing happening here: in this case, gcc seems to let the 1 fall out and not circle around!
The code might prove cryptic: if you're interested and need an explanation please don't hesitate to ask - I'll put it up someplace.
#ΤΖΩΤΖΙΟΥ
In reply to ΤΖΩΤΖΙΟΥ 's comments, I present modified version of above which depends on a upper limit for bit width.
#include <stdio.h>
#include <stdint.h>
typedef int32_t TYPE;
TYPE reverse(TYPE x, int bits)
{
TYPE m=~0;
switch(bits)
{
case 64:
x = (x&0xFFFFFFFF00000000&m)>>16 | (x&0x00000000FFFFFFFF&m)<<16;
case 32:
x = (x&0xFFFF0000FFFF0000&m)>>16 | (x&0x0000FFFF0000FFFF&m)<<16;
case 16:
x = (x&0xFF00FF00FF00FF00&m)>>8 | (x&0x00FF00FF00FF00FF&m)<<8;
case 8:
x = (x&0xF0F0F0F0F0F0F0F0&m)>>4 | (x&0x0F0F0F0F0F0F0F0F&m)<<4;
x = (x&0xCCCCCCCCCCCCCCCC&m)>>2 | (x&0x3333333333333333&m)<<2;
x = (x&0xAAAAAAAAAAAAAAAA&m)>>1 | (x&0x5555555555555555&m)<<1;
}
return x;
}
int main(int argc, char**argv)
{
TYPE x;
TYPE b = (TYPE)-1;
int bits;
if ( argc != 2 )
{
printf("Usage: %s hexadecimal\n", argv[0]);
return 1;
}
for(bits=1;b;b<<=1,bits++);
--bits;
printf("TYPE has %d bits\n", bits);
sscanf(argv[1],"%x", &x);
printf("0x%x\n",reverse(x, bits));
return 0;
}
Notes:
gcc will warn on the 64bit constants
the printfs will generate warnings too
If you need more than 64bit, the code should be simple enough to extend
I apologise in advance for the coding crimes I committed above - mercy good sir!
There's a nice collection of "Bit Twiddling Hacks", including a variety of simple and not-so simple bit reversing algorithms coded in C at http://graphics.stanford.edu/~seander/bithacks.html.
I personally like the "Obvious" algorigthm (http://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious) because, well, it's obvious. Some of the others may require less instructions to execute. If I really need to optimize the heck out of something I may choose the not-so-obvious but faster versions. Otherwise, for readability, maintainability, and portability I would choose the Obvious one.
Here is a more generally useful variation. Its advantage is its ability to work in situations where the bit length of the value to be reversed -- the codeword -- is unknown but is guaranteed not to exceed a value we'll call maxLength. A good example of this case is Huffman code decompression.
The code below works on codewords from 1 to 24 bits in length. It has been optimized for fast execution on a Pentium D. Note that it accesses the lookup table as many as 3 times per use. I experimented with many variations that reduced that number to 2 at the expense of a larger table (4096 and 65,536 entries). This version, with the 256-byte table, was the clear winner, partly because it is so advantageous for table data to be in the caches, and perhaps also because the processor has an 8-bit table lookup/translation instruction.
const unsigned char table[] = {
0x00,0x80,0x40,0xC0,0x20,0xA0,0x60,0xE0,0x10,0x90,0x50,0xD0,0x30,0xB0,0x70,0xF0,
0x08,0x88,0x48,0xC8,0x28,0xA8,0x68,0xE8,0x18,0x98,0x58,0xD8,0x38,0xB8,0x78,0xF8,
0x04,0x84,0x44,0xC4,0x24,0xA4,0x64,0xE4,0x14,0x94,0x54,0xD4,0x34,0xB4,0x74,0xF4,
0x0C,0x8C,0x4C,0xCC,0x2C,0xAC,0x6C,0xEC,0x1C,0x9C,0x5C,0xDC,0x3C,0xBC,0x7C,0xFC,
0x02,0x82,0x42,0xC2,0x22,0xA2,0x62,0xE2,0x12,0x92,0x52,0xD2,0x32,0xB2,0x72,0xF2,
0x0A,0x8A,0x4A,0xCA,0x2A,0xAA,0x6A,0xEA,0x1A,0x9A,0x5A,0xDA,0x3A,0xBA,0x7A,0xFA,
0x06,0x86,0x46,0xC6,0x26,0xA6,0x66,0xE6,0x16,0x96,0x56,0xD6,0x36,0xB6,0x76,0xF6,
0x0E,0x8E,0x4E,0xCE,0x2E,0xAE,0x6E,0xEE,0x1E,0x9E,0x5E,0xDE,0x3E,0xBE,0x7E,0xFE,
0x01,0x81,0x41,0xC1,0x21,0xA1,0x61,0xE1,0x11,0x91,0x51,0xD1,0x31,0xB1,0x71,0xF1,
0x09,0x89,0x49,0xC9,0x29,0xA9,0x69,0xE9,0x19,0x99,0x59,0xD9,0x39,0xB9,0x79,0xF9,
0x05,0x85,0x45,0xC5,0x25,0xA5,0x65,0xE5,0x15,0x95,0x55,0xD5,0x35,0xB5,0x75,0xF5,
0x0D,0x8D,0x4D,0xCD,0x2D,0xAD,0x6D,0xED,0x1D,0x9D,0x5D,0xDD,0x3D,0xBD,0x7D,0xFD,
0x03,0x83,0x43,0xC3,0x23,0xA3,0x63,0xE3,0x13,0x93,0x53,0xD3,0x33,0xB3,0x73,0xF3,
0x0B,0x8B,0x4B,0xCB,0x2B,0xAB,0x6B,0xEB,0x1B,0x9B,0x5B,0xDB,0x3B,0xBB,0x7B,0xFB,
0x07,0x87,0x47,0xC7,0x27,0xA7,0x67,0xE7,0x17,0x97,0x57,0xD7,0x37,0xB7,0x77,0xF7,
0x0F,0x8F,0x4F,0xCF,0x2F,0xAF,0x6F,0xEF,0x1F,0x9F,0x5F,0xDF,0x3F,0xBF,0x7F,0xFF};
const unsigned short masks[17] =
{0,0,0,0,0,0,0,0,0,0X0100,0X0300,0X0700,0X0F00,0X1F00,0X3F00,0X7F00,0XFF00};
unsigned long codeword; // value to be reversed, occupying the low 1-24 bits
unsigned char maxLength; // bit length of longest possible codeword (<= 24)
unsigned char sc; // shift count in bits and index into masks array
if (maxLength <= 8)
{
codeword = table[codeword << (8 - maxLength)];
}
else
{
sc = maxLength - 8;
if (maxLength <= 16)
{
codeword = (table[codeword & 0X00FF] << sc)
| table[codeword >> sc];
}
else if (maxLength & 1) // if maxLength is 17, 19, 21, or 23
{
codeword = (table[codeword & 0X00FF] << sc)
| table[codeword >> sc] |
(table[(codeword & masks[sc]) >> (sc - 8)] << 8);
}
else // if maxlength is 18, 20, 22, or 24
{
codeword = (table[codeword & 0X00FF] << sc)
| table[codeword >> sc]
| (table[(codeword & masks[sc]) >> (sc >> 1)] << (sc >> 1));
}
}
How about:
long temp = 0;
int counter = 0;
int number_of_bits = sizeof(value) * 8; // get the number of bits that represent value (assuming that it is aligned to a byte boundary)
while(value > 0) // loop until value is empty
{
temp <<= 1; // shift whatever was in temp left to create room for the next bit
temp |= (value & 0x01); // get the lsb from value and set as lsb in temp
value >>= 1; // shift value right by one to look at next lsb
counter++;
}
value = temp;
if (counter < number_of_bits)
{
value <<= counter-number_of_bits;
}
(I'm assuming that you know how many bits value holds and it is stored in number_of_bits)
Obviously temp needs to be the longest imaginable data type and when you copy temp back into value, all the extraneous bits in temp should magically vanish (I think!).
Or, the 'c' way would be to say :
while(value)
your choice
We can store the results of reversing all possible 1 byte sequences in an array (256 distinct entries), then use a combination of lookups into this table and some oring logic to get the reverse of integer.
Here is a variation and correction to TK's solution which might be clearer than the solutions by sundar. It takes single bits from t and pushes them into return_val:
typedef unsigned long TYPE;
#define TYPE_BITS sizeof(TYPE)*8
TYPE reverser(TYPE t)
{
unsigned int i;
TYPE return_val = 0
for(i = 0; i < TYPE_BITS; i++)
{/*foreach bit in TYPE*/
/* shift the value of return_val to the left and add the rightmost bit from t */
return_val = (return_val << 1) + (t & 1);
/* shift off the rightmost bit of t */
t = t >> 1;
}
return(return_val);
}
The generic approach hat would work for objects of any type of any size would be to reverse the of bytes of the object, and the reverse the order of bits in each byte. In this case the bit-level algorithm is tied to a concrete number of bits (a byte), while the "variable" logic (with regard to size) is lifted to the level of whole bytes.
Here's my generalization of freespace's solution (in case we one day get 128-bit machines). It results in jump-free code when compiled with gcc -O3, and is obviously insensitive to the definition of foo_t on sane machines. Unfortunately it does depend on shift being a power of 2!
#include <limits.h>
#include <stdio.h>
typedef unsigned long foo_t;
foo_t reverse(foo_t x)
{
int shift = sizeof (x) * CHAR_BIT / 2;
foo_t mask = (1 << shift) - 1;
int i;
for (i = 0; shift; i++) {
x = ((x & mask) << shift) | ((x & ~mask) >> shift);
shift >>= 1;
mask ^= (mask << shift);
}
return x;
}
int main() {
printf("reverse = 0x%08lx\n", reverse(0x12345678L));
}
In case bit-reversal is time critical, and mainly in conjunction with FFT, the best is to store the whole bit reversed array. In any case, this array will be smaller in size than the roots of unity that have to be precomputed in FFT Cooley-Tukey algorithm. An easy way to compute the array is:
int BitReverse[Size]; // Size is power of 2
void Init()
{
BitReverse[0] = 0;
for(int i = 0; i < Size/2; i++)
{
BitReverse[2*i] = BitReverse[i]/2;
BitReverse[2*i+1] = (BitReverse[i] + Size)/2;
}
} // end it's all

Resources