Packing two shorts into one int, dealing with negative and positive
Asked Answered
L

1

8

I'm making a class PackedUnsigned1616 which stores two unsigned shorts in one int, and a class PackedSigned1616 which stores two signed shorts in one int. I've read up on bitwise operations, but I'm still confused on how to deal with signed and unsigned and values that are larger or smaller that a short's range (they are passed in as two ints). Here's what I've got so far:

public final class PackedUnsigned1616 {
public final int field;

private static final int RIGHT = (2 << 15) - 1;
private static final int LEFT = ((2 << 31) - 1) ^ RIGHT;

public PackedUnsigned1616(int left, int right) {
    field = (left << 15) | (right & RIGHT);
}

public int getLeft() {
    return field >> 15;
}
public int getRight() {
    return field & RIGHT;
}

}

This whole concept is confusing me a lot, so if you could shed a little light on it, that would help tremendously.

Lycanthrope answered 8/5, 2011 at 20:29 Comment(4)
Well what is the desired behavior? The largest short you can represent is (2<<15)-1 so if you call the constructor with a number bigger than that, what should happen?Selfindulgent
Oh, sorry, I want it to be clampedLycanthrope
Is this for fun or to solve an actual problem?Salaried
It's for a particle simulator.Lycanthrope
L
11

Interesting way to initialize LEFT and RIGHT. Try this instead:

public final class PackedUnsigned1616 {
    public final int field;
    
    private static final int RIGHT = 0xFFFF;
    
    public PackedUnsigned1616(int left, int right) {
        field = (left << 16) | (right & RIGHT);
    }
    
    public int getLeft() {
        return field >>> 16; // >>> operator 0-fills from left
    }

    public int getRight() {
        return field & RIGHT;
    }
}

For signed values, I think all you need to do is modify getLeft and getRight as follows:

    public int getLeft() {
        return field >> 16; // sign bit is significant
    }

    public int getRight() {
        return (short) (field & RIGHT); // gets cast back to signed int
    }
Leister answered 8/5, 2011 at 20:34 Comment(5)
Thanks! But how would I go about making PackedSigned1616?Lycanthrope
@Ted - I've searched for 0xFFFF notation on the internet. Is this hexadecimal? What do the 0x stand for? In addition, the getLeft function for the unsigned version doesn't work. Use the values (5, 32767), it returns 10 and 32727. Same goes for (5, 32766) and (5, 27766)Lycanthrope
@cable729 - The 0xFFFF notation is a hex literal. It's defined in the Java Language Specification. As to the code not working, I fixed a bug in my code (which I inherited by copying your code :-0) where it was shifting by 15 instead of 16. Make sure you're using the revised version.Leister
Yeah I found that too :) Thanks for the help!Lycanthrope
For signed values you can return a shortDowning

© 2022 - 2024 — McMap. All rights reserved.