GetPiecewiseInteger()?

Scripted ALFA systems & related tech discussions (ACR)

Moderators: ALFA Administrators, Staff - Technical

Locked
User avatar
AcadiusLost
Chosen of Forumamus, God of Forums
Posts: 5061
Joined: Tue Oct 19, 2004 8:38 am
Location: Montara, CA [GMT -8]
Contact:

GetPiecewiseInteger()?

Post by AcadiusLost »

This is a function Ronan coded to pull an integer out of a range of bits in a larger integer, used frequently in the spawn system to cut down the number of LocalInt() reads and writes.

Code: Select all

const int INT_SIZE = 32;

int GetPiecewiseInteger(int nNum, int nStartBit, int nEndBit) {

    int nShift = INT_SIZE - 1 - nEndBit;
    return ((nNum << nShift) >>> (nShift + nStartBit));
}
However, whenever it tries to read a value that requires the full range of bits, it's resulting in a negative number somehow. say, for a 5-bit range (position 0 to position 5), of 10001 (should be 17), it's returning "-15". Any idea on how it can be fixed? The bit shifting operands are pretty close to greek to me, and I didn't even have latin in school, so... help would be appreciated.
User avatar
Burt
Nihilist
Posts: 1161
Joined: Sat Jan 03, 2004 5:23 pm
Location: In-and-Out Burger, Camrose

Post by Burt »

If you had a few more test results I might be able to figure it out. I have no idea what >>> is doing.
Jagoff.
User avatar
ç i p h é r
Retired
Posts: 2904
Joined: Fri Oct 21, 2005 4:12 pm
Location: US Central (GMT - 6)

Post by ç i p h é r »

Only if that integer is padded with leading 0's. Remember, an int is a signed integer, so you're dealing with signed arithmetic. Be careful of leading 1's.

In an 8 bit signed integer:

00010001 = 17
11110001 = -15

The leading bit in a signed integer is the signed bit where a 1 represents a negative integer and a 0 represents a positive one, so you must somehow be getting a 1 in the signed bit position. To calculate the decimal value of a negative binary number, you first have to take the 1's complement then add 1 to it:

So in the above 8 bit example:

11110001 = - (00001110 + 00000001) = - (00001111) = -15

The << and >> bit shift operators move bits to the left and right a specific number of positions. I *think* it'll also roll over, meaning if you shift left or right past the last bit position, it'll bring the bit around on the other end. A >>> discards anything shifted beyond the right most bit position and 0 fills from the left. The equation looks to be trying to strip off the unwanted leading bits then shifting down and zero padding, but I think it's off slightly.

Ex: INT_SIZE is 8.

Passing in a 17 (00010001) and requesting bit 5 (17, 5, 5) would result in:

nShift = 8-1-5 = 2;
((00010001 << 2)) >>> (2 + 5)) = ((01000100) >>> (7)) = 0!

So, it looks like the formula is slightly off. Here's a suggested tweak:

Code: Select all

int nShift = INT_SIZE - nEndBit;
((nNum << nShift) >>> (nShift + nStartBit - 1));
Ex: INT_SIZE is 8.

Passing in a 17 (00010001) and requesting bits 1-5 (17, 1, 5) would result in:

nShift = 8-5 = 3;
((00010001 << 3) >>> (3 + 1 - 1)) = ((10001000) >>> (3)) = 17

That look ok? What number are you passing into this function? There's always the possibility that the >>> operator is broken and isn't 0 padding or something.
User avatar
AcadiusLost
Chosen of Forumamus, God of Forums
Posts: 5061
Joined: Tue Oct 19, 2004 8:38 am
Location: Montara, CA [GMT -8]
Contact:

Post by AcadiusLost »

The spawn system composes things like spawn times (hour spawn in, hour spawn out, day spawn in, day spawn out, month spawn in, month spawn out) into a single 32-bit integer, so it can be read once by the spawning scripts, and the key values inferred based on their offsets, as divined by that PiecewiseInteger function.

I'd suspected something like the "top" bit being read as left-padding with 1's, since the handy "scientific" version of windows calculator was telling me that a negative integer happened when the left was padded with 1s, though not remembering anything about how signed integers are actually stored, I kind of stalled out on it.

I'll try your recommended change to the function, and see if that does the trick. Much obliged.
Ronan
Dungeon Master
Posts: 4611
Joined: Sun Feb 20, 2005 9:48 am

Post by Ronan »

Whoops :oops: I wonder if this is the bug that kept the last thing I was working on with the spawn sytem from working. I remember changing that function, but I thought I'd fixed a bug in it, not broken it.

Brut, >>> and <<< shift without rotating the shifted bits to the other side. They just add 0s as padding instead.
User avatar
AcadiusLost
Chosen of Forumamus, God of Forums
Posts: 5061
Joined: Tue Oct 19, 2004 8:38 am
Location: Montara, CA [GMT -8]
Contact:

Post by AcadiusLost »

Finally solved this one last night. Whenever there was a "1" in the leading position of the integer window, the >>> was turning the whole thing into a negative number (arithmetic rather than logical shift, if I've got my terminology correct).

Fix was in shifting left one less to preserve an extra bit of padding, then setting that extra padding bit to 0 before doing the rightward shift, to force it to be read as a positive number. Took a few tries to get everything to line up, but it works now. I'll commit the fixed version of acr_tools_i tonight along with the working version of the spawn system code.
Locked