- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
// https://github.com/TigerVNC/tigervnc/blob/8c6c584377feba0e3b99eecb3ef33b28cee318cb/java/com/jcraft/jsch/Buffer.java#L65-L85
public void putInt(int val) {
tmp[0]=(byte)(val >>> 24);
tmp[1]=(byte)(val >>> 16);
tmp[2]=(byte)(val >>> 8);
tmp[3]=(byte)(val);
System.arraycopy(tmp, 0, buffer, index, 4);
index+=4;
}
public void putLong(long val) {
tmp[0]=(byte)(val >>> 56);
tmp[1]=(byte)(val >>> 48);
tmp[2]=(byte)(val >>> 40);
tmp[3]=(byte)(val >>> 32);
System.arraycopy(tmp, 0, buffer, index, 4);
tmp[0]=(byte)(val >>> 24);
tmp[1]=(byte)(val >>> 16);
tmp[2]=(byte)(val >>> 8);
tmp[3]=(byte)(val);
System.arraycopy(tmp, 0, buffer, index+4, 4);
index+=8;
}
Жабовское байтоебство (судя по всему это такой ntohl) из реализации VNC.
Вот интересно, в жабке-то unsigned типов нет нихера, но почему-то сделали unsigned двоичный сдвиг (>>>), который работает для этих встроенных signed типов как если б это были unsigned. А как насчет unsigned умножения и деления (сложение и вычитание - то один хер, без разницы, если у нас two's complement)?
byte: The byte data type is an 8-bit signed two's complement integer. It has a minimum value of -128 and a maximum value of 127 (inclusive). The byte data type can be useful for saving memory in large arrays, where the memory savings actually matters. They can also be used in place of int where their limits help to clarify your code; the fact that a variable's range is limited can serve as a form of documentation.
short: The short data type is a 16-bit signed two's complement integer. It has a minimum value of -32,768 and a maximum value of 32,767 (inclusive). As with byte, the same guidelines apply: you can use a short to save memory in large arrays, in situations where the memory savings actually matters.
int: By default, the int data type is a 32-bit signed two's complement integer, which has a minimum value of -2^31 and a maximum value of 2^31-1. In Java SE 8 and later, you can use the int data type to represent an unsigned 32-bit integer, which has a minimum value of 0 and a maximum value of 2^32-1. Use the Integer class to use int data type as an unsigned integer. See the section The Number Classes for more information. Static methods like compareUnsigned, divideUnsigned etc have been added to the Integer class to support the arithmetic operations for unsigned integers.
long: The long data type is a 64-bit two's complement integer. The signed long has a minimum value of -2^63 and a maximum value of 2^63-1. In Java SE 8 and later, you can use the long data type to represent an unsigned 64-bit long, which has a minimum value of 0 and a maximum value of 2^64-1. Use this data type when you need a range of values wider than those provided by int. The Long class also contains methods like compareUnsigned, divideUnsigned etc to support arithmetic operations for unsigned long.
__m128i _mm_add_epi8 (__m128i a, __m128i b)
Интересно, зачем тогда вообще это правило про каст мелочи в int перед операциями? Оно же как чайник Рассела. Ни доказать ни опровергнуть.
uint8_t in[8];
uint16_t out[4];
out[0] = in[0] * in[1];
out[1] = in[2] * in[3];
out[2] = in[4] * in[5];
out[3] = in[6] * in[7];
Эмуляция через signed чтобы не трогать JVM?
Пусть x_u, y_u –— временные беззнаковые переменные (типа uint16_t), хранящие битовые копии x, y (типа int16_t).
Тогда x_u = x + pow(2,16)*h(x<0), где h –— функция Хевисайда;
y_u = y + pow(2,16)*h(y<0);
x_u*y_u = x*y + pow(2,16)*(y*h(x<0) + x*h(y<0)) + pow(2,32)*h(x<0)*h(y<0).
Выразим x и y через x_u и y_u соответственно и найдём значение x*y через беззнаковые переменные:
x*y = x_u*y_u - pow(2,16)*(y_u*h(x<0) + x_u*h(y<0)) +
+ pow(2,32)*h(x<0)*h(y<0)*(-1 + 1 + 1).
От последнего слагаемого толку нет, ибо его значение за пределом разрядности.
Итого:
https://ideone.com/DDqPGb
Теперь всё правильно:
https://ideone.com/7TE4No
Пусть x_s, y_s –— временные знаковые переменные (типа int16_t), хранящие копии x,y (типа uint16_t).
Тогда x_s = x - pow(2,16)*h(x>T-1);
y_s = y - pow(2,16)*h(y>T-1);
где T = pow(2,15) –— постоянная Тараса для данного типа данных.
x_s*y_s = x*y - pow(2,16)*(y*h(x>T-1) + x*h(y>T-1)) + pow(2,32)*h(x>T-1)*h(y>T-1).
Аналогично выразим x и y через x_s и y_s и получим:
x*y = x_s*y_s + pow(2,16)*(y_s*h(x>T-1) + x_s*h(y>T-1)) + pow(2,32)*h(x>T-1)*h(y>T-1)*(-1+1+1).
https://ideone.com/hinhoN
Но тогда придётся x1.s и y1.s предварительно кастануть в числа вдвое большей разрядности.
ЩЫ. это не лисп, я прост пероритеты забуа Перемножить модули и поставить соответствующий знак.
Вроде раьотает.
T + T = 0 (по модулю 2 в степени n).
Или так:
T = -T (по модулю 2 в степени n).
хотя тут могут быть ньюансы с endian
На темплейтах, чтобы конпелятор мог оптимизнуть под конкретную длину?
А если будешь использовать встроенный ассемблер в «gcc» или в «clang», то знак «%» ещё нужно удвоить, чтобы по ошибке не подставился мокрос.
Ну иначе байтоёбить было бы совсем уныло.