Split Array Cells in Java - java

outp is of unsigned short* type. Some manipulations need to be done depending on the mode where mode is a global variable. In the if-block val is assigned to outp at the calculated index. In if-else block first the address pointed by outc is calculated and then the value is assigned at that location which in turn leads to change in a paricular cell of outp.
void lds_ld(int val, int x, int y, int value, unsigned short* outp)
{
unsigned char *outc;
if(mode==1)
{
outp[y*width +x] = val;
}
else if (mode==2)
{
outc = (unsigned char *)outp +y*width + x;
*outc= value;
}
else
{
printf("Wrong mode");
}
}
I need to write a java code that performs the same function. So i have written:
void lds_ld(int val, int x, int y, int value, int outp[])
{
short outc[];
if(mode==1)
{
outp[y*width +x] = val;
}
else if (mode==2)
{
//what to write here
}
else
{
System.out.printf("Wrong mode");
}
}
To write the if-else block i some how need to first split each array cell into two and then calculate the index and assign value at that index and then convert this array back to int[] type. whole How can i do this?

Mode 2 seems to allow you to only edit the first byte of the short, so you might try this:
int arrayValue = outp[y * width + x];
int firstByte = (arrayValue >> 8) & 0xFF;
int secondByte = arrayValue & 0xFF;
firstByte = value;
//if you want to edit the second byte:
//secondByte = value;
outp[y * width + x] = (int)(firstByte << 8) + secondByte;

There are no pointers in java, so you can either work on the same array and remember index to start from or create new array and copy part of source array to the target:
// check array size calculations: I am not sure I completely 
// your logic but I am sure you do.
int outc = new int[outp - (y*width + x)]; understand
System.arraycopy(outp, y*width + x, outc, 0, outc.length);

Depending on how width is set, you are
1) either setting two shorts from an int
2) or you are setting one half of a short, another short, and another half of a short from the int. Which halves of the shorts you are changing (most or least significant) will depend on your CPU architecture (and maybe your compiler)
Since (2) is quite painful, let's assume (1), i.e. width % 2 == 0. In Java, you have to split the int for yourself instead of assuming casting magic:
// determine the least significant 16 bits of your int
short lower = (short)(value & 0xffff);
// determine the most significant 16 bits of your int
short upper = (short)(value >>> 16);
// same calculation as in C-code, but for a short-array instead of for char-array
int pos = (y * width + x) / 2;
// assuming little endian order in your array (similar to running the C-code on x86
outp[pos] = lower;
outp[pos + 1] = upper;
For option (2) you need to split your int into three values:
byte left = (byte)(value & 0xff);
short middle = (short)(value >>> 8);
byte right = (byte)(value >> 24);
After doing so, you can assign middle directly to outp[pos], but you must combine the left and right bytes with the existing values in the cell using bit-manipulation-operations:
if ((y * width + x) % 2) != 0) {
// still assuming little endianness
outp[pos - 1] = (short)(outp[pos - 1] & 0xff00 | left);
outp[pos + 1] = (short)(((right << 8) & 0xff00) | (outp[pos + 1] & 0xff));
}

Another way of doing the given task would be using java.nio.ByteBuffer classes:
import java.nio.*;
// Wrap outp into a ByteBuffer
ByteBuffer outpBuf = ByteBuffer.wrap(outp);
outpBuf.putInt(y * width + x, value);
Please note that ByteBuffer is initially using Big Endian ordering, so you need to use outpBuf.order(ByteOrder.LITTLE_ENDIAN) to get results equivalent to the direct bit-operations suggested by the other posters.

Related

Java: manipulate bits in a number

I was trying to implement a bit manipulation tool in Java.
I do not want to work with the Bitsetclass.
I am working with 64-bit Long values and implemented the following methods:
static final long toggle_bit(long number, int index) {
return (number ^= (1 << index));
}
static final long set_bit(long number, int index) {
return (number |= (1 << index));
}
static final long unset_bit(long number, int index) {
return (number &= ~(1 << index));
}
static final void print_bits(long number) {
String s = Long.toBinaryString(number);
String zeros = "0000000000000000000000000000000000000000000000000000000000000000"; //String of 64 zeros
s = zeros.substring(s.length()) + s;
System.out.println(s);
}
I think the best way of showing my problem is the result of this code:
>>> print_bits(set_bit(0L, 30));
0000000000000000000000000000000001000000000000000000000000000000
>>> print_bits(set_bit(0L, 31));
1111111111111111111111111111111110000000000000000000000000000000
I assume I am reaching negative values or something like that. I would
be very happy if someone could show me a very efficient way of
manipulating all 64 bits in a long-number.
Greetings,
Finn
Make index and the1 a long (declare as 1L) so that JVM doesn’t treat it as an integer.
I also have to note that in set_bits, |= (or equals) doesn’t account for when the bit is 1 but the desired value at the bit is 0
You are shifting an int value of 1. Try shifting a long value of 1, i.e. 1L << index

Efficient way to manipulate bits in byte array representing a bitfield

So, I have a byte array that represents a bitfield. A bit 1 at any index of a byte array implies that I have the corresponding piece and vice versa for a 0. Now, I need to change the bit value of 0 to 1, whenever I have the corresponding piece.
My question is, is it better if I convert the byte array to an int array and then change the corresponding value of the array index or is it simpler to do it in a byte array?
If it's the former, how can I convert the byte array to an integer array? If it's the latter, how do I change the value of the corresponding byte array?
To check if bit n is true
boolean get(int n, byte[] bitField)
{
return (bitField[n >> 3] & 1 << (n & 0x7)) != 0; //or use n / 8 and n % 8
}
To set bit n
void set(int n, byte[] bitField, boolean value)
{
if(value)
bitField[n >> 3] |= 1 << (n & 0x7);
else
bitField[n >> 3] &= ~(1 << (n & 0x7));
}
If you use a BitSet, it's a bit simpler
To instantiate
BitSet bitField = new BitSet(); //can specify size
To check if bit n is true
bitField.get(n);
To set bit n
bitField.set(n, value); //can also use set(int) and clear(int) instead

swapping the order of a multibyte

I have the following multi-byte represented in hex format:
0xdc, 0xd3
I can process the bytes in little endian () format to get the decimal value 54236:
List<Integer> packet = new LinkedList<Integer>(Arrays.asList(0xdc, 0xd3 ));
int idx=0;
int rpm = (int)readBytes(packet, idx, 2);
private long readBytes(List<Integer> packet, int idx, int size){
long val=0;
int element;
for(int i=0;i<size;i++, idx++){
element = packet.get(idx);
val |= element << (8 * i);
}
return val;
}
The above method produces the value as expected. However, now I want to get the value in the reverse order (big endian format), but it gives me some crazy value of 14471936:
private long bigEndianReadBytes(List<Integer> packet, int idx, int size){
long val=0;
int element;
for(int i=size;i>0;i--, idx++){
element = packet.get(idx);
val |= element << (8 * i);
}
return val;
}
What might be wrong with this method?
With #TimBiegeleisen answer (+1), you have good "manual" code to for converting bytes to values.
Have you considered using a ByteBuffer? It does all this for you and works with both Big Endian and Little Endian.
public static void main(String[] args) throws Exception {
ByteBuffer bb = ByteBuffer.allocate(2);
bb.put(new byte[] {(byte)0xdc, (byte)0xd3});
System.out.println(bb.order(ByteOrder.BIG_ENDIAN).getShort(0) & 0xFFFF);
System.out.println(bb.order(ByteOrder.LITTLE_ENDIAN).getShort(0) & 0xFFFF);
}
ANDing the result against 0xFFFF so the short result is promoted to an int, otherwise the result is a negative number because java works with signed data types.
Results:
56531
54236
The for loop in your bigEndianReadBytes() method should start by shifting size - 1 bytes, and end by shifting zero bytes (in the last iteration). Currently, you are shifting size bytes in the first iteration, and one byte in the last iteration. Try this code instead:
for (int i=size-1; i >= 0; i--, idx++) {
element = packet.get(idx);
val |= element << (8 * i);
}

Check partially known integer lies within a range

I have a peculiar problem for which I am looking for an efficient solution. I have a byte array which contains the most significant n bytes of an unsigned 4 byte integer (most sig byte first). The value of the remaining bytes (if any) are unknown. I need to check whether the partially known integer value could fall within a certain range (+ or - x) of a known integer. It's also valid for the integer represented by the byte array under test to wrap around.
I have a solution which works (below). The problem is that this solution performs way more comparisons than I believe is necessary and a whole load of comparisons will be duplicated in the scenario in which least sig bytes are unknown. I'm pretty sure it can be done more efficiently but can't figure out how. The scenario in which least significant bytes are unknown is an edge case so I might be able to live with it but it forms part of a system which needs to have low latency so if anyone could help with this that would be great.
Thanks in advance.
static final int BYTES_IN_INT = 4;
static final int BYTE_SHIFT = 010;
// partial integer byte array length guaranteed to be 1-4 so no checking necessary
static boolean checkPartialIntegerInRange(byte[] partialIntegerBytes, int expectedValue, int range)
{
boolean inRange = false;
if(partialIntegerBytes.length == BYTES_IN_INT)
{
// normal scenario, all bytes known
inRange = Math.abs(ByteBuffer.wrap(partialIntegerBytes).getInt() - expectedValue) <= range;
}
else
{
// we don't know least significant bytes, could have any value
// need to check if partially known int could lie in the range
int partialInteger = 0;
int mask = 0;
// build partial int and mask
for (int i = 0; i < partialIntegerBytes.length; i++)
{
int shift = ((BYTES_IN_INT - 1) - i) * BYTE_SHIFT;
// shift bytes to correct position
partialInteger |= (partialIntegerBytes[i] << shift);
// build up mask to mask off expected value for comparison
mask |= (0xFF << shift);
}
// check partial int falls in range
for (int i = -(range); i <= range; i++)
{
if (partialInteger == ((expectedValue + i) & mask))
{
inRange = true;
break;
}
}
}
return inRange;
}
EDIT: Thanks to the contributors below. Here is my new solution. Comments welcome.
static final int BYTES_IN_INT = 4;
static final int BYTE_SHIFT = 010;
static final int UBYTE_MASK = 0xFF;
static final long UINT_MASK = 0xFFFFFFFFl;
public static boolean checkPartialIntegerInRange(byte[] partialIntegerBytes, int expectedValue, int range)
{
boolean inRange;
if(partialIntegerBytes.length == BYTES_IN_INT)
{
inRange = Math.abs(ByteBuffer.wrap(partialIntegerBytes).getInt() - expectedValue) <= range;
}
else
{
int partialIntegerMin = 0;
int partialIntegerMax = 0;
for(int i=0; i < BYTES_IN_INT; i++)
{
int shift = ((BYTES_IN_INT - 1) - i) * BYTE_SHIFT;
if(i < partialIntegerBytes.length)
{
partialIntegerMin |= (((partialIntegerBytes[i] & UBYTE_MASK) << shift));
partialIntegerMax = partialIntegerMin;
}
else
{
partialIntegerMax |=(UBYTE_MASK << shift);
}
}
long partialMinUnsigned = partialIntegerMin & UINT_MASK;
long partialMaxUnsigned = partialIntegerMax & UINT_MASK;
long rangeMinUnsigned = (expectedValue - range) & UINT_MASK;
long rangeMaxUnsigned = (expectedValue + range) & UINT_MASK;
if(rangeMinUnsigned <= rangeMaxUnsigned)
{
inRange = partialMinUnsigned <= rangeMaxUnsigned && partialMaxUnsigned >= rangeMinUnsigned;
}
else
{
inRange = partialMinUnsigned <= rangeMaxUnsigned || partialMaxUnsigned >= rangeMinUnsigned;
}
}
return inRange;
}
Suppose you have one clockwise interval (x, y) and one normal interval (low, high) (each including their endpoints), determining whether they intersect can be done as (not tested):
if (x <= y) {
// (x, y) is a normal interval, use normal interval intersect
return low <= y && high >= x;
}
else {
// (x, y) wraps
return low <= y || high >= x;
}
To compare as unsigned integers, you can use longs (cast up with x & 0xffffffffL to counteract sign-extension) or Integer.compareUnsigned (in newer versions of Java) or, if you prefer you can add/subtract/xor both operands with Integer.MIN_VALUE.
Convert your unsigned bytes to an integer. Right-shift by 32-n (so your meaningful bytes are the min bytes). Right-shift your min/max integers by the same amount. If your shifted test value is equal to either shifted integer, it might be in the range. If it's between them, it's definitely in the range.
Presumably the sign bit on your integers is always zero (if not, just forcibly convert the negative to zero, since your test value can't be negative). But because that's only one bit, unless you were given all 32 bits as n, that shouldn't matter (it's not much of a problem in that special case).

A question in java.lang.Integer internal code

While looking in the code of the method:
Integer.toHexString
I found the following code :
public static String toHexString(int i) {
return toUnsignedString(i, 4);
}
private static String toUnsignedString(int i, int shift) {
char[] buf = new char[32];
int charPos = 32;
int radix = 1 << shift;
int mask = radix - 1;
do {
buf[--charPos] = digits[i & mask];
i >>>= shift;
} while (i != 0);
return new String(buf, charPos, (32 - charPos));
}
The question is, in toUnsignedString, why we create a char arr of 32 chars?
32 characters is how much you need to represent an int in binary (base-2, shift of 1, used by toBinaryString).
It could be sized exactly, but I guess it has never made business sense to attempt that optimisation.
Because that method is also called by toBinaryString(), and an int is up to 32 digits in binary.
Because the max value for an int in Java is : 2^31 - 1

Categories

Resources