2 * FastKeyErasureRNG: Fast-key-erasure random-number generator for Java
3 * Copyright (c) 2023 "dEajL3kA" <Cumpoing79@web.de>
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
6 * associated documentation files (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
8 * sub license, and/or sell copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions: The above copyright notice and this
10 * permission notice shall be included in all copies or substantial portions of the Software.
12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
13 * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
16 * OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 package io
.github
.deajl3ka
.fast_key_erasure
;
20 import java
.util
.Locale
;
21 import java
.util
.SplittableRandom
;
22 import java
.util
.concurrent
.BrokenBarrierException
;
23 import java
.util
.concurrent
.CyclicBarrier
;
25 public class GenerateCounter
{
27 private static final int THREAD_COUNT
= 8, WORDS
= 6, EXPECTED_DISTANCE
= 68;
29 private static final SplittableRandom splittableRandom
= new SplittableRandom(0x93C467E37DB0C7A4L
);
31 private static int bestDistance
= -1;
33 private static final Object mutex
= new Object();
35 private static final CyclicBarrier barrier
= new CyclicBarrier(THREAD_COUNT
);
37 private static class Int128
{
40 public Int128(final long hi
, final long lo
) {
45 public String
toString(final boolean verbose
) {
46 final String hexString
= toString();
50 final String upperString
= hexString
.toUpperCase(Locale
.ENGLISH
);
51 final StringBuilder sb
= new StringBuilder("{ ");
53 while (pos
< hexString
.length()) {
57 sb
.append("(byte)0x");
58 sb
.append(upperString
.subSequence(pos
, pos
+= 2));
60 return sb
.append(" }").toString();
64 public String
toString() {
65 return longToHexStr(hi
) + longToHexStr(lo
);
69 private static int distance(final Int128 a
,final Int128 b
) {
70 return Long
.bitCount(a
.hi ^ b
.hi
) + Long
.bitCount(a
.lo ^ b
.lo
);
73 public static void main(String
[] args
) {
74 final Thread
[] threads
= new Thread
[THREAD_COUNT
];
75 for (int tid
= 0; tid
< THREAD_COUNT
; ++tid
) {
76 threads
[tid
] = new Thread(GenerateCounter
::threadMain
);
79 for (final Thread thread
: threads
) {
82 } catch (InterruptedException e
) {
88 private static void threadMain() {
89 final Int128
[] values
= new Int128
[WORDS
];
90 final char[][] nibble
= new char[WORDS
][];
92 final SplittableRandom random
;
93 synchronized (mutex
) {
94 random
= splittableRandom
.split();
98 for (int i
= 0; i
< WORDS
; ++i
) {
101 final char[] thisNibbles
;
103 values
[i
] = new Int128(random
.nextLong(), random
.nextLong());
104 thisNibbles
= nibble
[i
] = values
[i
].toString().toCharArray();
105 } catch(NumberFormatException e
) {
106 continue generatorLoop
;
108 for (int k
= 0; k
< 31; ++k
) {
109 if (thisNibbles
[k
] == thisNibbles
[k
+ 1]) {
110 continue generatorLoop
;
113 for (int k
= 0; k
< 30; k
+= 2) {
114 if ((thisNibbles
[k
] == thisNibbles
[k
+ 2]) && (thisNibbles
[k
+1] == thisNibbles
[k
+ 3])) {
115 continue generatorLoop
;
118 for (int j
= 0; j
< i
; ++j
) {
119 final char[] otherNibbles
= nibble
[j
];
120 for (int k
= 0; k
< 32; ++k
) {
121 if (thisNibbles
[k
] == otherNibbles
[k
]) {
122 continue generatorLoop
;
130 int minDistance
= Integer
.MAX_VALUE
;
131 for (int i
= 0; i
< WORDS
; ++i
) {
132 for (int j
= i
+ 1; j
< WORDS
; ++j
) {
133 final int thisDistance
= distance(values
[i
], values
[j
]);
134 if (thisDistance
< minDistance
) {
135 minDistance
= thisDistance
;
140 synchronized (mutex
) {
141 if (minDistance
>= bestDistance
) {
142 bestDistance
= minDistance
;
143 System
.out
.printf("[%d]%n", bestDistance
);
144 for (int i
= 0; i
< WORDS
; ++i
) {
145 final String word
= new String(nibble
[i
]).toUpperCase(Locale
.ENGLISH
);
146 if (!values
[i
].toString().equalsIgnoreCase(word
)) {
147 throw new AssertionError("Whoops!");
149 System
.out
.println(word
);
151 System
.out
.println();
152 if (bestDistance
>= EXPECTED_DISTANCE
) {
153 for (int i
= 0; i
< WORDS
; ++i
) {
154 System
.out
.println(values
[i
].toString(true));
156 System
.out
.println();
163 } catch (InterruptedException
| BrokenBarrierException e
) {
167 synchronized (mutex
) {
168 if (bestDistance
>= EXPECTED_DISTANCE
) {
175 private static String
longToHexStr(final long value
) {
176 final String str
= Long
.toHexString(value
);
177 switch (str
.length()) {
185 throw new NumberFormatException();