We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hallo to everyone.
My problem is to have the upper 4 Byte result of a multiply. For example:
unsigned int a=1000000000;//only example value unsigned int b=10000000000; unsigned int c;
the result of a*b = 0x8AC7230489E80000 How to get the upper 4 Bytes: 0x8AC72304 How to get the lower 4 Bytes: 0x89E80000
Can anybody help? I have to programm a super-fast-interrupt-routine for an microcontroller, there is not enough time for floating point.
You'd want one of the long long integer types then.
Hello,
long long may be a way, but i only need a 32-bit result, the upper 4 byte or the lower 4 byte. Maybee someone has a programm-example :-)
Regards
So extract the MSLong or LSLong of the 64-bit result. Shifting and masking, or unions work on long longs too.
union U64_ { unsigned long long ull; unsigned long ul[2]; }; unsigned long multiplier; unsigned long multiplicand; union U64_ product; unsigned long product_msl; unsigned long product_lsl; product.ull = (unsigned long long)multplicand * multiplier; product_msl = product.ul[1]; /* Assuming little-endian */ product_lsl = product.ul[0]; /* Assuming little-endian */
Quickly typed, not tested :-(
s/multplicand/multiplicand/
Hi, i tried several version of something like
unsigned int a=3162277661; unsigned int b=3162277660; unsigned int c; c=((a*b)>>32)&0xFFFFFFFF;
but i get wrong result or ARM COMPILER V2.40c, ADIDEMO\LONG_LONG_7.C: '>>': out of range shift factor has been truncated *** WARNING C200 IN LINE 16 OF ADIDEMO\LONG_LONG_7.C: '>>': out of range shift factor has been truncated
Regarding the shift operator:
"If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined."
but i get wrong result or
No, the result is not wrong, what you're doing is wrong. You're expecting the compiler to automatically expand the result to 64 bits, which it won't do.
Either you do it in assembly (ARM has very nice multiply instructions that can calculate the upper part, the lower part, or all 64 bits of a 32 bit * 32 bit multiplication), or you tell the compiler that it needs to use a 64 bit integer datatype. I wouldn't expect it to come up with optimal (super-fast) code however.
Define them as long long int (unsigned int if you desire)
long long int a; long long int b; long long int c;
int lower32; int upper32;
c = a * b;
lower32 = *((u32 *) &c); upper32 = *(((u32 *) &c) + 1); // little endian assumed
Don't worry the the last assignments look ugly. The compiler will easily optimize this to a direct 32-bit fetch of the value.
I hope you have a program-example in assembler or C for me, how to get this upper 4byte of the multiplikation (int * int).
Of cause i know The Compiler is allways right, i'am allways doing wrong... but how to change to the other side ;-) ;-) ;-)
:-)
"I hope you have a program-example in assembler or C"
Any particular reason you don't like the examples provide thusfar?
Any particular reason you don't like the examples provide thusfar? as i havent used unions before, i'am afraid of getting large and slow code.
I will test it tomorrow, i promise :-)
I hope you have a program-example in assembler or C
Actually, I don't.
I have a copy of the ARM instruction set here, which describes the MUL (32x32 bit multiplication, least significant 32 bits as result) and SMMUL (32x32 bit multiplication, most significant 32 bits as result) assembly instructions.
If you don't want to get your hands dirty doing assembly, there's enough examples here already that show how to do it in C using long long ints. Of course, this might not be super-fast, depending on the compiler. Maybe the compiler is smart enough to recognize something along the lines of
unsigned long long r; unsigned long a, b; ... r = (unsigned long long) a * b;
as a single 32x32 multiplication, maybe it is not. Take your chances.
as i havent used unions before,
Maybe you need to learn to walk before trying to run a marathon ?
i'am afraid of getting large and slow code.
Since you're not familiar with the internal architecture of ARM, how do you know that something will generate large and slow code ?
Of course, you can also try to do everything with 32 bit integers, using some elementary school-level maths:
(off the top of my head)
unsigned int a, b, ah, al, bh, bl, r1, r2, r3, r4, msw, lsw; ... ah = a >> 16; al = a & 0x0000FFFF; bh = b >> 16; bl = b & 0x0000FFFF; r1 = ah * bh; r2 = ah * bl; r3 = al * bh; r4 = bl * bl; msb = r1 + r2 >> 16 + r3 >> 16; r2 = r2 << 16; r3 = r3 << 16; lsb = r2 + r3; if((lsb < r2)) { msb = msb + 1; } lsb += r4; if((lsb < r4)) { msb = msb + 1; }
Do you think this kludge is going to be faster (on an ARM) than using long long ints ?
r4 = bl * bl;
should be
r4 = al * bl;
and all occurrences of msb/lsb should be msw/lsw.
Hello, this is perfect but very slow code...
long long int a; long long int b; long long int c; int lower32; int upper32; c = a * b; lower32 = *((u32 *) &c); upper32 = *(((u32 *) &c) + 1); // little endian assumed
i had to replace u32 by unsigned int :-)
Another side effect: Writing
a=3162277660;// = 0XBC7C871C
gives the result a=0XFFFFFFFFBC7C871C
a=0xBC7C871C;// = 3162277660
gives the result a=0X00000000BC7C871C