How to rotate 128 bit number in Java - java

I am trying to implement a cipher that uses a 128 bit key. Part of the key schedule is to rotate the key 29 bits to the right, but I am unsure how to do that since there is no single data type in Java that can hold the whole key. I have it stored in two longs, one for the upper half and one for the lower half. Here is the bit math that I have that I thought should work but isn't doing the trick:
keyLower >>>= 29;
keyLower |= keyUpper << 35;
keyUpper >>>= 29;
keyUpper |= keyLowerCopy << 29;
Can anyone help me out?

You have a typo on the last line:
// vv
keyUpper |= keyLowerCopy << 29;
Looks like it's supposed to be << 35.

Take a look at BigInteger.
Immutable arbitrary-precision integers. [...] Semantics of shift operations extend those of Java's shift operators to allow for negative shift distances. A right-shift with a negative shift distance results in a left shift, and vice-versa. The unsigned right shift operator (>>>) is omitted, as this operation makes little sense in combination with the "infinite word size" abstraction provided by this class.

Related

Bit manipulation in Java - 2s complement and flipping bits

I was recently looking into some problems with but manipulation in Java and I came up with two questions.
1) Firstly, I came up to the problem of flipping all the bits in a number.
I found this solution:
public class Solution {
public int flipAllBits(int num) {
int mask = (1 << (int)Math.floor(Math.log(num)/Math.log(2))+1) - 1;
return num ^ mask;
}
}
But what happens when k = 32 bits? Can the 1 be shifted 33 times?
What I understand from the code (although it doesn't really make sense), the mask is 0111111.(31 1's)....1 and not 32 1's, as someone would expect. And therefore when num is a really large number this would fail.
2) Another question I had was determining when something is a bit sequence in 2s complement or just a normal bit sequence. For example I read that 1010 when flipped is 0110 which is -10 but also 6. Which one is it and how do we know?
Thanks.
1) The Math object calls are not necessary. Flipping all the bits in any ordinal type in Java (or C) is not an arithmatic operation. It is a bitwise operation. Using the '^' operator, simply using 1- as an operand will work regardless of the sizeof int in C/C++ or a Java template with with the ordinal type as a parameter T. The tilde '~' operator is the other option.
T i = 0xf0f0f0f0;
System.out.println(T.toHexString(i));
i ^= -1;
System.out.println(T.toHexString(i));
i = ~ i;
System.out.println(T.toHexString(i));
2) Since the entire range of integers maps to the entire range of integers in a 2's compliment transform, it is not possible to detect whether a number is or is not 2's complement unless one knows the range of numbers from which the 2's complement might be calculated and the two sets (before and after) are mutually exclusive.
That mask computation is fairly inscrutable, I'm going to guess that it (attempts to, since you mention it's wrong) make a mask up to and including the highest set bit. Whether that's useful for "flipping all bits" is an other possible point of discussion, since to me at least, "all bits" means all 32 of them, not some number that depends on the value. But if that's what you want then that's what you want. Especially combined with that second question, that looks like a mistake to me, so you'd be implementing the wrong thing from the start - see near the bottom.
Anyway, the mask can be generated with some reasonably nice bitmath, which does not create any doubt about possible edge cases (eg Math.log(0) is probably bad, and k=32 corresponds with negative numbers which are also probably bad to put into a log):
int m = num | (num >> 16);
m |= m >> 8;
m |= m >> 4;
m |= m >> 2;
m |= m >> 1;
return num ^ m;
Note that this function has odd properties, it almost always returns an unsigned-lower number than went in, except at 0. It flips bits so the name is not completely wrong, but flipAllBits(flipAllBits(x)) != x (usually), while the name suggests it should be an involution.
As for the second question, there is nothing to determine. Two's complement is scheme by which you can interpret a bitvector - any bitvector. So it's really a choice you make; to interpret a given bitvector that way or some other way. In Java the "default" interpretation is two's complement (eg toString will print an int by interpreting it according to its two's complement meaning), but you don't have to go along with it, you can (with care) treat int as unsigned, or as an array of booleans, or several bitfields packed together, etc.
If you wanted to invert all the bits but made the common mistake to assume that the number of bits in an int is variable (and that you therefore needed to compute a mask that covers "all bits"), I have some great news for you, because inverting all bits is a lot easier:
return ~num;
If you were reading "invert all bits" in the context of two's complement, it would have the above meaning, so all bits, including those left of the highest set bit.

(Java) Put negative short's bits to an interger

I want to put a short integer (16 bits) into tail of a 32 bits integer (I'm compressing some small-range numbers to an unique integer). But didn't found a better looking way than bellow, I have to use two operation, can it be better?
short sh = -1; // 16 bits 1
int zip = 0; // last 16 bits presents a short number
System.out.println("Wrong way, maybe many of us will try first:");
zip |= sh; // expect 0xffff
System.out.println(Integer.toHexString(zip)); // but 0xffffffff
System.out.println("Simple way, right but looks ugly, two operations");
zip = 0;
zip |= sh << 16 >>> 16; // expect 0xffff
System.out.println(Integer.toHexString(zip)); // yeah
System.out.println("Is there a nicer looking way, one operation for example?");
All bitwise operations in Java are done using ints or longs, therefore you don't have too much choice here; and casting a shorter primitive type whose sign bit is set will "expand" the sign bit to all "newer created" bits.
There is a solution to do it "in one line", but that will still be two operations:
zip |= (sh & 0xffff);
Note, it pretty much requires that zip is 0 to start with, or at least that its 16 low bits are 0.

bitwise operator >>> in hashCode

I have two related questions:
the bitwise operator >>> means that we are shifting the binary number by those many places while filling 0 in the Most Significant Bit. But, then why does the following operation yields the same number: 5>>>32 yields 5 and -5>>>32 yields -5. Because if the above description is correct then both these operations would have yielded 0 as the final result.
In continuation to above, As per Effective Java book, we should use (int) (f ^ (f >>> 32)) (in case the field is long) while calculating the hash code (if the field is long). Why do we do that and what's the explanation
5 can be represented as 0101 if you shift it by 1 bit i.e 5>>>1 this will result as 0010=2
If the promoted type of the left-hand operand is int, only the five
lowest-order bits of the right-hand operand are used as the shift
distance. It is as if the right-hand operand were subjected to a
bitwise logical AND operator & (ยง15.22.1) with the mask value 0x1f.
The shift distance actually used is therefore always in the range 0 to
31, inclusive.
When you shift an integer with the << or >> operator and the shift
distance is greater than or equal to 32, you take the shift distance
mod 32 (in other words, you mask off all but the low order 5 bits of
the shift distance). This can be very counterintuitive. For example (i> >> 32) == i, for every integer i. You might expect it to shift the entire number off to the right, returning 0 for positive inputs and -1
for negative inputs, but it doesn't; it simply returns i, because (i
<< (32 & 0x1f)) == (i << 0) == i.
Answer to your first question is here why is 1>>32 == 1?
The second question answer, in short, is that in such way the whole long value is used(not a part of it) and note that it is probably the fastest way to do this.
I know this question has been answered long back, but I tried an example to get more clarification and I guess it'll others too.
long x = 3231147483648l;
System.out.println(Long.toBinaryString(x));
System.out.println(Long.toBinaryString(x >>> 32));
System.out.println(Long.toBinaryString(x ^ (x >>> 32)));
System.out.println(Long.toBinaryString((int) x ^ (x >>> 32)));
This prints -
101111000001001111011001011110001000000000
1011110000
101111000001001111011001011110000011110000
1001111011001011110000011110000
As #avrilfanomar mentions, this XORs first 32 bits of long with the other 32 bits and unsigned right shift operator helps us in doing this. Since we want to use this long field while calculating the hashcode, directly casting the long to int would mean that long fields differing only in the upper 32 bits will contribute the same value to the hashcode. This potentially means that two objects differing only in this field will have same hashcode and it'll be stored in the same bucket (with say a list to resolve collision) and this impacts the performance of hash-based collections. Hence, this operation.

For bitwise operations in Java, do I need to care that most numeric types in Java are signed?

This is a really basic question, but I've never fully convinced myself that my intuitive answer of "it makes no difference" is correct, so maybe someone has a good way to understand this:
If all I want to do with one of the primitive numeric types in Java is bitwise arithmetic, can I simply treat it as if it was an unsigned value or do I need to avoid negative numbers, i.e. keep the highest order bit always set to 0? For example, can I use an int as if it was an unsigned 32-bit number, or should I only use the lowest 31 bits?
I'm looking for as general an answer as possible, but let me give an example: Let's say I want to store 32 flags. Can I store all of them in a single int, if I use something like
store = store & ~(1 << index) | (value << index)
to set flag index to value and something like
return (store & (1 << index)) != 0
to retrieve flag index? Or could I run into any sort of issues with this or similar code if I ever set the flag with index 31 to 1?
I know I need to always be using >>> instead of >> for right shifting, but is this the only concern? Or could there be other things going wrong related to the two's complement representation of negative numbers when I use the highest bit?
I know I need to always be using >>> instead of >> for right shifting, but is this the only concern?
Yes, this is the only concern. Shifting left works the same on signed and unsigned numbers; same goes for ANDing, ORing, and XORing. As long as you use >>> for shifting right, you can use all 32 bits of a signed int.
There are legitimate reasons to use >> as well in that context (a common case is when making a mask that should be 0 or -1 directly, without having to negate a mask that is 0 or 1), so there is really no concern at all. Just be careful of what you're doing to make sure it matches your intent.
Operations that care about signedness (ie they have distinct signed and unsigned forms with different semantics) are:
right shift
division (unsigned form not available in Java)
modulo (unsigned form not available in Java)
comparisons (except equality) (unsigned forms not available in Java)
Operations that don't care about signedness are:
and
or
xor
addition
subtraction
two's complement negation (-x means ~x + 1)
one's complement (~x means -x - 1)
left shift
multiplication

Change Value of First Bit in Binary String - Java

I have a program which works with genetic algorithms and generates an 8-bit binary string (chromosome consisting of eight genes).
I would like to know how I would go about changing / flipping the first gene/bit.
For example:
Original chromosome:
01010101
Changed chromosome:
11010101 //First bit has been changed
If the first bit has a value of 1, I would like to 'flip' it to make it a 0; and, obviously, if the first bit in the array/chromosome is a 0, I would like to 'flip' that to a 1.
Thank you.
You could use the following:
chromosome ^= 0x80;
The xor-assignment (^=) flips the chromosome bits that are set in the right-hand side expression, and 0x80 is 10000000 in binary.
More generally, to flip the k-th bit (with the least significant bit being bit 0):
chromosome ^= (1 << k);

Categories

Resources