I have been tasked to rewrite a small program written in C++ to C#.
But I came across this line that I couldn't understand fully. Is it concatenating the string length to the string or the pointer?
int n = _keyData * int(*(int*)(_chap + strlen(_chap) - 4));
This is the variables:
short _ver = 12;
short _keyData = short(_ver * _ver);
char _chap[100]; // Hold time with format [%02d-%02d %02d:%02d:%02d:%03d]
*(int*)(_chap + strlen(_chap) - 4) is a strict aliasing violation. Reinterpreting raw bytes as an int is type punning and is not allowed in C++ (even though some compilers tolerate it).
To fix it (assuming a little-endian system), you can rewrite it like this:
short _ver = 12;
short _keyData = short(_ver * _ver);
char _chap[100]; // Hold time with format [%02d-%02d %02d:%02d:%02d:%03d]
int len = strlen(_chap);
int x = (int)(((unsigned)_chap[len - 1] << 24) |
((unsigned)_chap[len - 2] << 16) |
((unsigned)_chap[len - 3] << 8) |
(unsigned)_chap[len - 4]);
int n = _keyData * x;
Coincidently, it should be easy to port this to C# now.
Related
C#.NET:
public int NextRandom(int n) {
int n2 = (n + 7) * 3;
n = ((int)((uint)n >> 8) | n << 24);
n ^= ((int)((uint)n >> 7) & 0x3FF) * ((int)((uint)n >> 22) & 0x3FF) + 5 * (n2 + 3);
return n;
}
NextRandom(1337);
C# RETURN: 956321482
PHP:
public function NextRandom($n) {
$n2 = ($n + 7) * 3;
$n = ((int)(abs($n) >> 8) | $n << 24);
$n ^= ((int)(abs($n) >> 7) & 0x3FF) * ((int)(abs($n) >> 22) &
0x3FF) + 5 * ($n2 + 3);
return $n;
}
NextRandom(1337);
PHP RETURN: 22431157962
What is wrong in my PHP code?
Tanks for help.
SOLVED:
I add
$n &= 0xFFFFFFFF;
to put the integer back into 32-bit range.
the result of your operation is 22431157962 the value that PHP shows
But the max value an int(32bit) can show is 2147483647, so it can not fit in the return type(int) you have defined, try changing the return type to long(64 bit number) (+any other cast if needed) and you should be fine, not a master at PHP but i think PHP is using 64 bit number in this case
Just for more debug info, the way to debug this is look at HEX values
956321482 = 0x39004ECA
22431157962 = 0x539004ECA
If you look close the first 32bit are same, but your number needs more than that
The following code is used to compact multiple values in a long. The long is used as a key in a C++ unordered_map. It allows me to use the map with a number instead of a complex structure and ifs on each properties. The map searching to be as efficient as possible.
DWORD tmpNo = object->room->details->No;
unsigned char compactNo = tmpNo ;
unsigned __int16 smallX = object->x;
unsigned __int16 smallY = object->y;
unsigned __int64 longCode = 0;
longCode = (item->code[0] << 56) |
(item->code[1] << 48) |
(item->code[2] << 40) |
(compactNo << 32) |
(smallX << 24) |
(smallY << 8);
Am I using the | operator correctly here ?
To recover the values, I tryed :
unsigned char c0 = key >> 56;
unsigned char c1 = key >> 48;
unsigned char c2 = key >> 40;
etc, but it didn't work.
Is it because the original item->code chars are chars and not unsigned chars (the values are always positive though) ?
Also, in an ideal world, the long's values would be recovered in a .NET DLL. Is it possible to do so in C# ?
C# has a byte type for an 8-bit value, but otherwise the logic is similar.
Your | logic looks fine (except you should be shifting smallX by 16 and smallY by 0)
It would help if you gave a complete example.
But assuming that item->code[0] is a char or int (signed or unsigned), you need to convert it to a 64 bit type before shifting, otherwise you end up with undefined behaviour, and the wrong answer.
Something like
((unsigned __int64) item->code[0]) << 56
should work better.
I think that stdint.h is very useful to understand this kind of implementation (sized integers are very meaningful). So here's the code:
#include <stdio.h>
#include <stdint.h>
int8_t getValue8(int index, uint64_t container) {
return (uint8_t)((container >> (index * 8)) & 0XFF);
}
void setValue8(int index, uint64_t* container, uint8_t value) {
// get left part of container including the last byte (cleared by ~0xFF mask) to be used by value
int shift = index * 8;
uint64_t mask = (uint64_t) ~0xFF;
uint64_t left = (*container >> shift) & mask;
left = (left | value) << shift;
// right part of container (complement)
mask = ((uint64_t)1 << ++shift) - 1;
uint64_t right = *container & mask;
// update container
*container = left | right;
}
int main() {
uint64_t* container; // container: can contain 8 chars (64-bit sized container)
uint64_t containerValue = 0;
int n = 8; // n value must be <= 8 considering a 64-bit sized container
uint8_t chars[n]; // eight char values to be stored
// add/set values to container
container = &containerValue;
int i;
for (i = 0; i < n; ++i) {
chars[i] = (uint8_t)((i+1)*10);
setValue8(i, container, chars[i]);
printf("setValue8(%d, container, %d)\n", i, chars[i]);
}
// get values from container
for (i = 0; i < n; ++i) {
printf("getValue8(%d, container)=%d\n", i, getValue8(i, *container));
}
return 0;
}
The code use only bit masks and some bitwise operations, and so you can easily port it to C#. If you have any questions about it just ask. I hope I have been helpful.
We are doing some performance optimizations in our project and with the profiler I came upon the following method:
private int CalculateAdcValues(byte lowIndex)
{
byte middleIndex = (byte)(lowIndex + 1);
byte highIndex = (byte)(lowIndex + 2);
// samples is a byte[]
retrun (int)((int)(samples[highIndex] << 24)
+ (int)(samples[middleIndex] << 16) + (int)(samples[lowIndex] << 8));
}
This method is already pretty fast with ~1µs per execution, but it is called ~100.000 times per second and so it takes ~10% of the CPU.
Does anyone have an idea how to further improve this method?
EDIT:
Current solution:
fixed (byte* p = samples)
{
for (; loopIndex < 61; loopIndex += 3)
{
adcValues[k++] = *((int*)(p + loopIndex)) << 8;
}
}
This takes <40% of the time then before (the "whole method" took ~35µs per call before and ~13µs now). The for-loop actualy takes more time then the calcualtion now...
I strongly suspect that after casting to byte, your indexes are being converted back to int anyway for use in the array indexing operation. That will be cheap, but may not be entirely free. So get rid of the casts, unless you were using the conversion to byte to effectively get the index within the range 0..255. At that point you can get rid of the separate local variables, too.
Additionally, your casts to int are no-ops as the shift operations are only defined on int and higher types.
Finally, using | may be faster than +:
private int CalculateAdcValues(byte lowIndex)
{
return (samples[lowIndex + 2] << 24) |
(samples[lowIndex + 1] << 16) |
(samples[lowIndex] << 8);
}
(Why is there nothing in the bottom 8 bits? Is that deliberate? Note that the result will end up being negative if samples[lowIndex + 2] has its top bit set - is that okay?)
Seeing that you have a friendly endianess, go unsafe
unsafe int CalculateAdcValuesFast1(int lowIndex)
{
fixed (byte* p = &samples[lowIndex])
{
return *(int*)p << 8;
}
}
On x86 about 30% faster. Not much gain as I hoped. About 40% when on x64.
As suggested by #CodeInChaos:
var bounds = samples.Length - 3;
fixed (byte* p = samples)
{
for (int i = 0; i < 1000000000; i++)
{
var r = CalculateAdcValuesFast2(p, i % bounds); // about 2x faster
// or inlined:
var r = *((int*)(p + i % bounds)) << 8; // about 3x faster
// do something
}
}
unsafe object CalculateAdcValuesFast2(byte* p1, int p2)
{
return *((int*)(p1 + p2)) << 8;
}
May be following can be little faster. I have removed casting to integer.
var middleIndex = (byte)(lowIndex + 1);
var highIndex = (byte)(lowIndex + 2);
return (this.samples[highIndex] << 24) + (this.samples[middleIndex] << 16) + (this.samples[lowIndex] << 8);
I need to read a byte from a .bin but starting from the specific bit, for example:
If I have this two bytes:
01010111 10101100
The program should be able to read from any bit, let's say starting in bit number 3 (or index 2):
01[010111 10]101100
And the result should be 01011110
I can read a byte starting from any bit except when the starting bit is the one at the end of a byte: 0101011[1 ...] //returns something different..
my code is:
byte readByte(int indexInBits, byte[] bytes)
{
int actualByte = (indexInBits+1)/8;
int indexInByte = (indexInBits)%8;
int b1 = bytes[actualByte] << indexInByte;
int b2 = bytes[actualByte+1] >> 8 - indexInByte;
return (byte)(b1 + b2);
}
What is wrong with it?
Thanks
byte ReadByte(int index, byte[] bytes)
{
int bytePos = index / 8;
int bitPos = index % 8;
int byte1 = bytes[bytePos] << bitPos;
int byte2 = bytes[bytePos + 1] >> 8 - bitPos;
return (byte)(byte1 + byte2);
}
I couldn't verify this right now, but this should work as expected.
Working with a base64 encoding for Azure (http://msdn.microsoft.com/en-us/library/dd135726.aspx) and I dont seem to work out how to get the required string back. I'm able to do this in C# where I do the following.
int blockId = 5000;
var blockIdBytes = BitConverter.GetBytes(blockId);
Console.WriteLine(blockIdBytes);
string blockIdBase64 = Convert.ToBase64String(blockIdBytes);
Console.WriteLine(blockIdBase64);
Which prints out (in LINQPad):
Byte[] (4 items)
| 136 |
| 19 |
| 0 |
| 0 |
iBMAAA==
In Qt/C++ I tried a few aporaches, all of them returning the wrong value.
const int a = 5000;
QByteArray b;
for(int i = 0; i != sizeof(a); ++i) {
b.append((char)(a&(0xFF << i) >>i));
}
qDebug() << b.toBase64(); // "iIiIiA=="
qDebug() << QByteArray::number(a).toBase64(); // "NTAwMA=="
qDebug() << QString::number(a).toUtf8().toBase64(); // "NTAwMA=="
How can I get the same result as the C# version?
See my comment for the problem with your for loop. It's shifting by one bit more each pass, but actually it should be 8 bits. Personally, I prefer this to a loop:
b.append(static_cast<char>(a >> 24));
b.append(static_cast<char>((a >> 16) & 0xff));
b.append(static_cast<char>((a >> 8) & 0xff));
b.append(static_cast<char>(a & 0xff));
The code above is for network standard byte order (big endian). Flip the order of the four operations from last to first for little endian byte order.
I ended up doing the following:
QByteArray temp;
int blockId = 5000;
for(int i = 0; i != sizeof(blockId); i++) {
temp.append((char)(blockId >> (i * 8)));
}
qDebug() << temp.toBase64(); // "iBMAAA==" which is correct
I think this would be clearer, though may be claimed to be ill styled...
int i = 0x01020304;
char (&bytes)[4] = (char (&)[4])i;
and you can access each byte directly with bytes[0], bytes[1], ... and do what ever you want to do with them.