I have an array of 5 bytes (fixed length). First 21 bits represent a counter and the rest 19 some id. I need to increment the counter by one. How do I do that?
This answer is based on the memory layout as I understand it from the OP's comments:
array[0]: bits 0..7 are counter bits 0..7 (lsb)
array[1]: bits 0..7 are counter bits 8..15
array[2]: bits 0..4 are counter bits 16..20 (msb)
bits 5..7 are part of the id
array[3]: bits 0..7 are part of the id
array[3]: bits 0..7 are part of the id
Then
int byte0 = (int) array[0] & 0xff;
int byte1 = (int) array[1] & 0xff;
int byte2 = (int) array[2] & 0x1f;
int count = byte0 | (byte1 << 8) | (byte2 << 16);
count = (count+1) & 0x1fffff;
array[0] = (byte) (count & 0x0000ff);
array[1] = (byte) ((count & 0x00ff00) >> 8);
array[2] = (array[2] & 0xe0) | (byte) ((count & 0x1f0000) >> 16);
should do the trick.
I'm not sure I solved your problem. Since the memory layout is not described in detail, I assumed a layout. You can obtain the counter, increase it by 1, and then set the counter. If the layout is as desired, it needs to be fully tested. I'm not dealing with data overflow situations, and you may need to add some restrictions.
public class Test {
public static void main(String[] args) {
byte[] bytes = new byte[5];
bytes[2] = 5;
for (int i = 0; i <= 0x1fffff; i++) {
setCount(bytes, i);
if (getCount(bytes) != i) {
System.out.println(i);
debug(bytes);
}
}
}
public static int getCount(byte[] bytes) {
return ((bytes[2] >> 3) & 0x1f) + ((bytes[1] << 5) & 0x1fff) + ((bytes[0] << 13) & 0x1fffff);
}
public static void setCount(byte[] bytes, int count) {
bytes[0] = (byte) (count >> 13 & 0xff);
bytes[1] = (byte) (count >> 5 & 0xff);
bytes[2] = (byte) ((bytes[2] & 0x7) + ((count & 0x1f) << 3));
}
public static void debug(byte[] bytes) {
for (byte b : bytes) {
for (int i = 7; i >= 0; i--) {
System.out.print(b >> i & 1);
}
System.out.print(" ");
}
System.out.println();
System.out.println("Count:" + getCount(bytes));
}
public static void printInt(int num) {
for (int i = 31; i >= 0; i--) {
System.out.print(num >> i & 1);
}
System.out.println();
}
}
I'm not sure I solved your problem.
public class Main
{
public static void main(String[] args)
{
//################
//# BIG ENDIAN #
//################
//initial counter == 1 (b0000_0000_0000_0000_0000_1)
//initial ids == 3 (b000_0000_0000_0000_0011)
byte[] array = { 0, 0, 8, 0, 3 };
int counter = ((array[0] & 0xFF) << 13)
| ((array[1] & 0xFF) << 5)
| ((array[2] & 0xF8) >> 3);
System.out.println(counter); //1
++counter;
System.out.println(counter); //2
//Repack the counter into the array.
array[0] = (byte)((counter & 0x1FE000) >> 13);
array[1] = (byte)((counter & 0x1FE0) >> 5);
array[2] = (byte)(((counter & 0x1F) << 3)| (array[2] & 0x7));
System.out.println(Arrays.toString(array)); //[0, 0, 16, 0, 3]
//Retry & Verify
counter = ((array[0] & 0xFF) << 13) //Same as above. Nothing is changed.
| ((array[1] & 0xFF) << 5)
| ((array[2] & 0xF8) >> 3);
System.out.println(counter); //2
++counter;
System.out.println(counter); //3
//###################
//# LITTLE ENDIAN #
//###################
//initial ids == 3 (b0000_0000_0000_0000_011)
//initial counter == 1 (b0_0000_0000_0000_0000_0001)
byte[] arr = { 0, 0, 96, 0, 1 };
counter = ((arr[2] & 0x1F) << 16)
| ((arr[3] & 0xFF) << 8)
| (arr[4] & 0xFF);
System.out.println(counter); //1
++counter;
System.out.println(counter); //2
//Repack the counter into the array.
arr[2] = (byte)((arr[2] & 0xE0) | ((counter & 0x1F0000) >> 16));
arr[3] = (byte)((counter & 0xFF00) >> 8);
arr[4] = (byte)(counter & 0xFF);
System.out.println(Arrays.toString(arr)); //[0, 0, 96, 0, 2]
//Retry & Verify
counter = ((arr[2] & 0x1F) << 16) //Same as above. Nothing is changed.
| ((arr[3] & 0xFF) << 8)
| (arr[4] & 0xFF);
System.out.println(counter); //2
++counter;
System.out.println(counter); //3
}
}
Related
I am developing software in JavaCard to addition points in ECC.
the issue is I need some basis operations, so for the moment, I need multiplication and inversion, I already have addition and subtraction.
I was trying to develop montgomery multiplication but it is for GF(2^m) (I think).
so my example is:
public static void multiplicationGF_p2(){
byte A = (byte) 7;
byte p = (byte) 5;
byte B = (byte) 2;
byte C = (byte) 0;
byte n = (byte)8;
byte i = (byte)(n - 1);
for(; i >= 0; i--){
C = (byte)(((C & 0xFF) + (C & 0xFF) ) + ((A & 0xff) << getBytePos(B,i)));
if((C & 0xFF) >= (byte)(p & 0xFF)){
C = (byte) ((C & 0xFF)-(p & 0xFF));
}
if((C & 0xFF) >= (byte)(p & 0xFF)){
C = (byte) ((C & 0xFF)-(p & 0xFF));
}
}
}
for example A = 2, B =3, p= 3 C must be 0, C = A. B (mode p)
but this example A = 7, B=2, p=5 , C must be 4, but I have 49.
can someone help me with that?
more methods:
public static byte getBytePos(byte b, byte pos){
return (byte)(((b & 0xff) >> pos) & 1);
}
I am trying to be simple, for the moment, but the idea is make multiplication of very big number like arrays[10] of bytes
I have supposed that something was wrong here:
C = (byte)(((C & 0xFF) + (C & 0xFF) ) + ((A & 0xff) << getBytePos(B,i)));
I have created a method to multiply byte numbers, not just using shift to the right <<
So:
public static byte bmult(byte x, byte y){
byte total = (byte)0;
byte i;
byte n = (byte)8; // multiplication for 8 bits or 1 byte
for(i = n ; i >= 0 ; i--)
{
total <<= 1;
if( (((y & 0xff) & (1 << i)) >> i) != (byte)0 )
{
total = (byte)(total + x);
}
}
return total;
}
so then I have added it in my original method, (in the line marked):
C = (byte)(((C & 0xFF) + (C & 0xFF) ) + bmult(A, getBytePos(B,i)) );
for now it is working correctly, I need to test it more
someone has another solution ?
I convert a short number to a 3 byte array using the following code:
static byte[] convertTo3ByteArray(short s) {
byte[] ret = new byte[3];
ret[0] = (byte) (s & 0xff);
ret[1] = (byte) ((s >> 8) & 0xff);
ret[2] = (byte) (0x00);
return ret;
}
This works very well.
I found a code on Stackoverflow to convert the array back to a number:
static int convertToInt(byte[] b) {
return ((b[0] << 0) | (b[1] << 8) | (b[2] << 16));
}
And when I convert 258 to byte array, and then use this code, it returns 258.
But for number 675, this code returns -93.
How do I have to change the convertToShort method to get 675 back?
I suppose it has something to do with bitshift and loss of data? Or signed bytes?
Try with this modified method:
static int convertToShort(byte[] b) {
return (((b[0] & 0xFF) << 0) | ((b[1] & 0xFF) << 8) | ((b[2] & 0xFF) << 16));
}
In the array some bytes are negative, you need to convert them back to "positive values" with byteVal & 0xFF before doing the bit shift
A short has 16 bits of information, so that would be two bytes. When you try to store a third byte with | (b[2] << 16), it would go off the end of the short's bits, which is a problem. I.e. you can't do what you want to.
Changing to using a char datatype will fix this issue as they are the only unsigned type in Java:
https://stackoverflow.com/a/21089624/1590490
static char[] convertTo3ByteArray(short s) {
char[] ret = new char[3];
ret[0] = (char) (s & 0xff);
ret[1] = (char) ((s >> 8) & 0xff);
ret[2] = (char) (0x00);
return ret;
}
static int convertToShort(char[] b) {
return ((b[0]) | (b[1] << 8) | (b[2] << 16)); // the original << 0 shift does nothing
}
I am trying to convert a byte to integer. All the searches I have done use byte[] which I assume is any array. I want to convert F byte (not b as show below) but it gives error to change: not applicable to the argument.
byte F;
mmInStream.read(packetBytes);
b [counter]= packetBytes[0];
F=b [counter];
counter++;
temp = byteToInt(b); //Convert byte to int
Here is a byte To Int I found on one of the sites.
private int byteToInt(byte[] b) {
int value= 0;
for(int i=0;i<b.length;i++){
int n=(b[i]<0?(int)b[i]+256:(int)b[i])<<(8*i);
value+=n;
}
return value;
}
Simply do:
byte b = ...;
int signedInt = b; // For negative bytes, resulting in negative ints
int unsignedInt = 0xFF & b; // For negative bytes, resulting in positive ints
FYI: An int is 4 bytes. So, that is the reason why the methods you found on the internet are using an array of bytes. They assume you pass an array of 4 bytes, which will be stitched together to make an int.
you can use this:
int i = 234;
byte b = (byte) i;
System.out.println(b); // -22
int i2 = b & 0xFF;
System.out.println(i2); // 234
or this one also:
public static byte[] intToByteArray(int a)
{
byte[] ret = new byte[4];
ret[3] = (byte) (a & 0xFF);
ret[2] = (byte) ((a >> 8) & 0xFF);
ret[1] = (byte) ((a >> 16) & 0xFF);
ret[0] = (byte) ((a >> 24) & 0xFF);
return ret;
}
and
public static int byteArrayToInt(byte[] b)
{
return (b[3] & 0xFF) + ((b[2] & 0xFF) << 8) + ((b[1] & 0xFF) << 16) + ((b[0] & 0xFF) << 24);
}
if b is unsigned
int i = b & 0xff;
The following code attempts to store 4 longs in a byte array. Random access is important which is why I'm not doing this with byte streams. Why is the below code not working? Can you think of a more efficent way to do this?
public static void storeLong(long value, byte[] buf, int offset) {
buf[offset] = (byte) (value & 0xFFL);
buf[offset+1] = (byte) ((value >>> 8) & 0xFFL);
buf[offset+2] = (byte) ((value >>> 16) & 0xFFL);
buf[offset+3] = (byte) ((value >>> 24) & 0xFFL);
buf[offset+4] = (byte) ((value >>> 32) & 0xFFL);
buf[offset+5] = (byte) ((value >>> 40) & 0xFFL);
buf[offset+6] = (byte) ((value >>> 48) & 0xFFL);
buf[offset+7] = (byte) ((value >>> 56) & 0xFFL);
}
public static long retrieveLong(byte[] buf, int offset) {
return ((long)buf[offset])
+ (((long)buf[offset+1])<<8)
+ (((long)buf[offset+2])<<16)
+ (((long)buf[offset+3])<<24)
+ (((long)buf[offset+4])<<32)
+ (((long)buf[offset+5])<<40)
+ (((long)buf[offset+6])<<48)
+ (((long)buf[offset+7])<<56);
}
public static void main(String[] args) {
byte[] buf = new byte[32];
storeLong(-1, buf, 0);
storeLong(1, buf, 8);
storeLong(Long.MAX_VALUE, buf, 16);
storeLong(Long.MIN_VALUE, buf, 24);
System.out.println(-1);
System.out.println(1);
System.out.println(Long.MAX_VALUE);
System.out.println(Long.MIN_VALUE);
System.out.println(retrieveLong(buf, 0));
System.out.println(retrieveLong(buf, 8));
System.out.println(retrieveLong(buf, 16));
System.out.println(retrieveLong(buf, 24));
}
The output I get from the above is the following. You can see that the first four numbers do not match the next 4:
-1
1
9223372036854775807
-9223372036854775808
-72340172838076673
1
9151031864016699135
-9223372036854775808
Don't use + and byte is signed:
public static long retrieveLong(byte[] buf, int offset) {
return ((long)buf[offset] & 255)
| (((long)buf[offset + 1] & 255) << 8)
| (((long)buf[offset + 2] & 255) << 16)
| (((long)buf[offset + 3] & 255) << 24)
| (((long)buf[offset + 4] & 255) << 32)
| (((long)buf[offset + 5] & 255) << 40)
| (((long)buf[offset + 6] & 255) << 48)
| (((long)buf[offset + 7] & 255) << 56);
}
You have to and each byte with 255 to make it 'unsigned'. Also you have to use binary or instead of add.
I did some tests and found that using a java.nio.LongBuffer is twice as fast as my code
ByteBuffer bb = ByteBuffer.allocate(4*8);
LongBuffer lb = bb.asLongBuffer();
lb.put(0, -1);
lb.put(1, 1);
lb.put(2, Long.MAX_VALUE);
lb.put(3, Long.MIN_VALUE);
System.out.println(lb.get(0));
System.out.println(lb.get(1));
System.out.println(lb.get(2));
System.out.println(lb.get(3));
I can then get the byte array using bb.array()
Thanks to Louis Wasserman and Rene Jeschke for their efforts
I need to store data as LITTLE_ENDIAN instead of default BIG_ENDIAN.
Here's my sample code:
for (int i = 0; i < logo.length; i++) {
logoArray[i] = ((Integer) logo[i]).byteValue();
logoArray[i] = (byte) (((logoArray[i] & 1) << 7) + ((logoArray[i] & 2) << 5) + ((logoArray[i] & 4) << 3)
+ ((logoArray[i] & 8) << 1) + ((logoArray[i] & 16) >> 1) + ((logoArray[i] & 32) >> 3)
+ ((logoArray[i] & 64) >> 5) + ((logoArray[i] & 128) >> 7));
}
How should it be rewritten with ByteBuffer, for LITTLE_ENDIAN, as the following code doesn't work for me:
ByteBuffer record = ByteBuffer.allocate(logo.length);
record.order(ByteOrder.LITTLE_ENDIAN);
...
record.put(((Integer) logo[i]).byteValue());
...
record.array(); // get
ByteBuffer will work for you, if you use putInt and not put.
record.putInt((Integer) logo[i]);
A byte array (as Integer.byteValue()) has no "endianness" so it is stored as it is.
As andcoz says, the endian isn't taken into account when you put one byte at a time. Here is an example to show you how to do it:
import java.nio.*;
public class Test {
public static void main(String[] args) {
int[] logo = { 0xAABBCCDD, 0x11223344 };
byte[] logoLE = new byte[logo.length * 4];
ByteBuffer rec = ByteBuffer.wrap(logoLE).order(ByteOrder.LITTLE_ENDIAN);
for (int i = 0; i < logo.length; i++)
rec.putInt(logo[i]);
// Debug printouts...
System.out.println("logo:");
for (int b : logo)
System.out.println(Integer.toHexString((b < 0 ? b + 256 : b)));
System.out.println("\nlogoLE:");
int tmp = 0;
for (byte b : logoLE) {
System.out.print(Integer.toHexString((b < 0 ? b + 256 : b)));
if (++tmp % 4 == 0)
System.out.println();
}
}
}
Output:
logo:
aabbccdd
11223344
logoLE:
ddccbbaa
44332211