@@ -37,6 +37,57 @@ public class BQSpaceUtils {
3737 * @param quantQueryByte the byte array to store the transposed query vector
3838 */
3939 public static void transposeHalfByte (byte [] q , byte [] quantQueryByte ) {
40+ int limit = q .length - 7 ;
41+ int i = 0 ;
42+ int index = 0 ;
43+ for (; i < limit ; i += 8 , index ++) {
44+ assert q [i ] >= 0 && q [i ] <= 15 ;
45+ assert q [i + 1 ] >= 0 && q [i + 1 ] <= 15 ;
46+ assert q [i + 2 ] >= 0 && q [i + 2 ] <= 15 ;
47+ assert q [i + 3 ] >= 0 && q [i + 3 ] <= 15 ;
48+ assert q [i + 4 ] >= 0 && q [i + 4 ] <= 15 ;
49+ assert q [i + 5 ] >= 0 && q [i + 5 ] <= 15 ;
50+ assert q [i + 6 ] >= 0 && q [i + 6 ] <= 15 ;
51+ assert q [i + 7 ] >= 0 && q [i + 7 ] <= 15 ;
52+ int lowerByte = (q [i ] & 1 ) << 7 | (q [i + 1 ] & 1 ) << 6 | (q [i + 2 ] & 1 ) << 5 | (q [i + 3 ] & 1 ) << 4 | (q [i + 4 ] & 1 ) << 3 | (q [i
53+ + 5 ] & 1 ) << 2 | (q [i + 6 ] & 1 ) << 1 | (q [i + 7 ] & 1 );
54+ int lowerMiddleByte = ((q [i ] >> 1 ) & 1 ) << 7 | ((q [i + 1 ] >> 1 ) & 1 ) << 6 | ((q [i + 2 ] >> 1 ) & 1 ) << 5 | ((q [i + 3 ] >> 1 ) & 1 )
55+ << 4 | ((q [i + 4 ] >> 1 ) & 1 ) << 3 | ((q [i + 5 ] >> 1 ) & 1 ) << 2 | ((q [i + 6 ] >> 1 ) & 1 ) << 1 | ((q [i + 7 ] >> 1 ) & 1 );
56+ int upperMiddleByte = ((q [i ] >> 2 ) & 1 ) << 7 | ((q [i + 1 ] >> 2 ) & 1 ) << 6 | ((q [i + 2 ] >> 2 ) & 1 ) << 5 | ((q [i + 3 ] >> 2 ) & 1 )
57+ << 4 | ((q [i + 4 ] >> 2 ) & 1 ) << 3 | ((q [i + 5 ] >> 2 ) & 1 ) << 2 | ((q [i + 6 ] >> 2 ) & 1 ) << 1 | ((q [i + 7 ] >> 2 ) & 1 );
58+ int upperByte = ((q [i ] >> 3 ) & 1 ) << 7 | ((q [i + 1 ] >> 3 ) & 1 ) << 6 | ((q [i + 2 ] >> 3 ) & 1 ) << 5 | ((q [i + 3 ] >> 3 ) & 1 ) << 4
59+ | ((q [i + 4 ] >> 3 ) & 1 ) << 3 | ((q [i + 5 ] >> 3 ) & 1 ) << 2 | ((q [i + 6 ] >> 3 ) & 1 ) << 1 | ((q [i + 7 ] >> 3 ) & 1 );
60+ quantQueryByte [index ] = (byte ) lowerByte ;
61+ quantQueryByte [index + quantQueryByte .length / 4 ] = (byte ) lowerMiddleByte ;
62+ quantQueryByte [index + quantQueryByte .length / 2 ] = (byte ) upperMiddleByte ;
63+ quantQueryByte [index + 3 * quantQueryByte .length / 4 ] = (byte ) upperByte ;
64+ }
65+ if (i == q .length ) {
66+ return ; // all done
67+ }
68+ int lowerByte = 0 ;
69+ int lowerMiddleByte = 0 ;
70+ int upperMiddleByte = 0 ;
71+ int upperByte = 0 ;
72+ for (int j = 7 ; i < q .length ; j --, i ++) {
73+ lowerByte |= (q [i ] & 1 ) << j ;
74+ lowerMiddleByte |= ((q [i ] >> 1 ) & 1 ) << j ;
75+ upperMiddleByte |= ((q [i ] >> 2 ) & 1 ) << j ;
76+ upperByte |= ((q [i ] >> 3 ) & 1 ) << j ;
77+ }
78+ quantQueryByte [index ] = (byte ) lowerByte ;
79+ quantQueryByte [index + quantQueryByte .length / 4 ] = (byte ) lowerMiddleByte ;
80+ quantQueryByte [index + quantQueryByte .length / 2 ] = (byte ) upperMiddleByte ;
81+ quantQueryByte [index + 3 * quantQueryByte .length / 4 ] = (byte ) upperByte ;
82+ }
83+
84+ /**
85+ * Same as {@link #transposeHalfByte(byte[], byte[])} but with more readable but slower code.
86+ *
87+ * @param q the query vector, assumed to be half-byte quantized with values between 0 and 15
88+ * @param quantQueryByte the byte array to store the transposed query vector
89+ * */
90+ public static void transposeHalfByteLegacy (byte [] q , byte [] quantQueryByte ) {
4091 for (int i = 0 ; i < q .length ;) {
4192 assert q [i ] >= 0 && q [i ] <= 15 ;
4293 int lowerByte = 0 ;
@@ -66,6 +117,57 @@ public static void transposeHalfByte(byte[] q, byte[] quantQueryByte) {
66117 * @param quantQueryByte the byte array to store the transposed query vector
67118 * */
68119 public static void transposeHalfByte (int [] q , byte [] quantQueryByte ) {
120+ int limit = q .length - 7 ;
121+ int i = 0 ;
122+ int index = 0 ;
123+ for (; i < limit ; i += 8 , index ++) {
124+ assert q [i ] >= 0 && q [i ] <= 15 ;
125+ assert q [i + 1 ] >= 0 && q [i + 1 ] <= 15 ;
126+ assert q [i + 2 ] >= 0 && q [i + 2 ] <= 15 ;
127+ assert q [i + 3 ] >= 0 && q [i + 3 ] <= 15 ;
128+ assert q [i + 4 ] >= 0 && q [i + 4 ] <= 15 ;
129+ assert q [i + 5 ] >= 0 && q [i + 5 ] <= 15 ;
130+ assert q [i + 6 ] >= 0 && q [i + 6 ] <= 15 ;
131+ assert q [i + 7 ] >= 0 && q [i + 7 ] <= 15 ;
132+ int lowerByte = (q [i ] & 1 ) << 7 | (q [i + 1 ] & 1 ) << 6 | (q [i + 2 ] & 1 ) << 5 | (q [i + 3 ] & 1 ) << 4 | (q [i + 4 ] & 1 ) << 3 | (q [i
133+ + 5 ] & 1 ) << 2 | (q [i + 6 ] & 1 ) << 1 | (q [i + 7 ] & 1 );
134+ int lowerMiddleByte = ((q [i ] >> 1 ) & 1 ) << 7 | ((q [i + 1 ] >> 1 ) & 1 ) << 6 | ((q [i + 2 ] >> 1 ) & 1 ) << 5 | ((q [i + 3 ] >> 1 ) & 1 )
135+ << 4 | ((q [i + 4 ] >> 1 ) & 1 ) << 3 | ((q [i + 5 ] >> 1 ) & 1 ) << 2 | ((q [i + 6 ] >> 1 ) & 1 ) << 1 | ((q [i + 7 ] >> 1 ) & 1 );
136+ int upperMiddleByte = ((q [i ] >> 2 ) & 1 ) << 7 | ((q [i + 1 ] >> 2 ) & 1 ) << 6 | ((q [i + 2 ] >> 2 ) & 1 ) << 5 | ((q [i + 3 ] >> 2 ) & 1 )
137+ << 4 | ((q [i + 4 ] >> 2 ) & 1 ) << 3 | ((q [i + 5 ] >> 2 ) & 1 ) << 2 | ((q [i + 6 ] >> 2 ) & 1 ) << 1 | ((q [i + 7 ] >> 2 ) & 1 );
138+ int upperByte = ((q [i ] >> 3 ) & 1 ) << 7 | ((q [i + 1 ] >> 3 ) & 1 ) << 6 | ((q [i + 2 ] >> 3 ) & 1 ) << 5 | ((q [i + 3 ] >> 3 ) & 1 ) << 4
139+ | ((q [i + 4 ] >> 3 ) & 1 ) << 3 | ((q [i + 5 ] >> 3 ) & 1 ) << 2 | ((q [i + 6 ] >> 3 ) & 1 ) << 1 | ((q [i + 7 ] >> 3 ) & 1 );
140+ quantQueryByte [index ] = (byte ) lowerByte ;
141+ quantQueryByte [index + quantQueryByte .length / 4 ] = (byte ) lowerMiddleByte ;
142+ quantQueryByte [index + quantQueryByte .length / 2 ] = (byte ) upperMiddleByte ;
143+ quantQueryByte [index + 3 * quantQueryByte .length / 4 ] = (byte ) upperByte ;
144+ }
145+ if (i == q .length ) {
146+ return ; // all done
147+ }
148+ int lowerByte = 0 ;
149+ int lowerMiddleByte = 0 ;
150+ int upperMiddleByte = 0 ;
151+ int upperByte = 0 ;
152+ for (int j = 7 ; i < q .length ; j --, i ++) {
153+ lowerByte |= (q [i ] & 1 ) << j ;
154+ lowerMiddleByte |= ((q [i ] >> 1 ) & 1 ) << j ;
155+ upperMiddleByte |= ((q [i ] >> 2 ) & 1 ) << j ;
156+ upperByte |= ((q [i ] >> 3 ) & 1 ) << j ;
157+ }
158+ quantQueryByte [index ] = (byte ) lowerByte ;
159+ quantQueryByte [index + quantQueryByte .length / 4 ] = (byte ) lowerMiddleByte ;
160+ quantQueryByte [index + quantQueryByte .length / 2 ] = (byte ) upperMiddleByte ;
161+ quantQueryByte [index + 3 * quantQueryByte .length / 4 ] = (byte ) upperByte ;
162+ }
163+
164+ /**
165+ * Same as {@link #transposeHalfByte(int[], byte[])} but with more readable but slower code.
166+ *
167+ * @param q the query vector, assumed to be half-byte quantized with values between 0 and 15
168+ * @param quantQueryByte the byte array to store the transposed query vector
169+ * */
170+ public static void transposeHalfByteLegacy (int [] q , byte [] quantQueryByte ) {
69171 for (int i = 0 ; i < q .length ;) {
70172 assert q [i ] >= 0 && q [i ] <= 15 ;
71173 int lowerByte = 0 ;
0 commit comments