1
2
3
4
5
6 package io.github.olyutorskii.aletojio.bijection;
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 public final class ParitySpreader {
33
34 private static final String ERRMSG_ODDLEN = "length must be even";
35 private static final String ERRMSG_TOOSMALL = "too small length";
36 private static final String ERRMSG_TOOLARGE = "too large length";
37
38 private static final int MASK_BYTE = (1 << Byte.SIZE) - 1;
39
40
41
42
43
44 private ParitySpreader() {
45 assert false;
46 }
47
48
49
50
51
52
53
54
55 public static int spread(int iVal) {
56 int i0 = iVal & MASK_BYTE;
57 int i1 = (iVal >>> (Byte.SIZE * 1)) & MASK_BYTE;
58 int i2 = (iVal >>> (Byte.SIZE * 2)) & MASK_BYTE;
59 int i3 = (iVal >>> (Byte.SIZE * 3)) & MASK_BYTE;
60
61 int xorVal = (i0 ^ i1) ^ (i2 ^ i3);
62
63 int o0 = i0 ^ xorVal;
64 int o1 = (i1 ^ xorVal) << (Byte.SIZE * 1);
65 int o2 = (i2 ^ xorVal) << (Byte.SIZE * 2);
66 int o3 = (i3 ^ xorVal) << (Byte.SIZE * 3);
67
68 int result = (o0 ^ o1) ^ (o2 ^ o3);
69
70 return result;
71 }
72
73
74
75
76
77
78
79
80
81 public static void spread(byte[] bytes, int length)
82 throws IndexOutOfBoundsException, IllegalArgumentException {
83 if (length < 0) throw new IndexOutOfBoundsException(ERRMSG_TOOSMALL);
84 if ((length & 1) == 1) throw new IllegalArgumentException(ERRMSG_ODDLEN);
85 if (bytes.length < length) throw new IndexOutOfBoundsException(ERRMSG_TOOLARGE);
86
87 byte xorVal = 0;
88 for (int idx = 0; idx < length; idx++) {
89 xorVal ^= bytes[idx];
90 }
91
92 for (int idx = 0; idx < length; idx++) {
93 byte bVal = bytes[idx];
94 bVal ^= xorVal;
95 bytes[idx] = bVal;
96 }
97
98 return;
99 }
100
101 }