Skip to content

Commit caa45e2

Browse files
committed
add golomb code
1 parent 285263e commit caa45e2

File tree

5 files changed

+106
-1
lines changed

5 files changed

+106
-1
lines changed

docs/HoffmanAndGolombCoding.pdf

947 KB
Binary file not shown.

src/main/java/com/github/myibu/algorithm/data/Bits.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public class Bits {
1414
private int size;
1515
private int used;
1616

17-
Bits() {
17+
public Bits() {
1818
table = new Bit[INITIAL_SIZE];
1919
this.used = 0;
2020
this.size = INITIAL_SIZE;
@@ -373,6 +373,10 @@ public static Bits ofZero(int len) {
373373
return bits;
374374
}
375375

376+
public static Bits ofZero() {
377+
return ofZero(1);
378+
}
379+
376380
public static Bits ofOne(int len) {
377381
Bits bits = new Bits();
378382
bits.expand(len);
@@ -383,6 +387,10 @@ public static Bits ofOne(int len) {
383387
return bits;
384388
}
385389

390+
public static Bits ofOne() {
391+
return ofOne(1);
392+
}
393+
386394
public Bits append(Bits other) {
387395
int newLen = this.used + other.used;
388396
expand(newLen);
@@ -391,6 +399,14 @@ public Bits append(Bits other) {
391399
return this;
392400
}
393401

402+
public Bits append(Bit bit) {
403+
int newLen = this.used + 1;
404+
expand(newLen);
405+
table[this.used] = bit;
406+
this.used += 1;
407+
return this;
408+
}
409+
394410
private void expand(int newLen) {
395411
if (newLen <= this.size) {
396412
return;
@@ -426,6 +442,10 @@ static void subBitsRangeCheck(int fromIndex, int toIndex, int size) {
426442
") > toIndex(" + toIndex + ")");
427443
}
428444

445+
public Bit[] table(){
446+
return this.table;
447+
}
448+
429449
@Override
430450
public String toString() {
431451
StringBuilder builder = new StringBuilder();
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.github.myibu.algorithm.endode;
2+
/**
3+
* Golomb code
4+
* @author myibu
5+
* Created on 2021/10/12
6+
*/
7+
public interface Encoder {
8+
9+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package com.github.myibu.algorithm.endode;
2+
3+
import com.github.myibu.algorithm.data.Bits;
4+
5+
/**
6+
* Golomb code
7+
* see <a herf="https://en.wikipedia.org/wiki/Golomb_coding#Simple_algorithm">https://en.wikipedia.org/wiki/Golomb_coding#Simple_algorithm</a>
8+
* @author myibu
9+
* Created on 2021/10/12
10+
*/
11+
public class GolombEncoder implements Encoder {
12+
/**
13+
*
14+
* @param n the value to encode
15+
* @param m m, like 5
16+
* @return the length of encoded bits
17+
*/
18+
public Bits encode(int n, int m) {
19+
Bits bits = new Bits();
20+
// 向下取整
21+
int q = (int)Math.floor(n * 1.0 / m);
22+
bits.append(Bits.ofOne(Math.max(0, q))).append(Bits.ofZero(1));
23+
int r = n % m;
24+
int k = (int)(Math.ceil(Math.log(m) / Math.log(2)));
25+
if ((m & 0x01) == 0) {
26+
return bits.append(encodeToStandardBinary(r, k));
27+
} else {
28+
// truncated binary encoding
29+
if (r < Math.pow(2, k) - m) {
30+
return bits.append(encodeToTruncatedBinary(r, m));
31+
} else {
32+
return bits.append(encodeToTruncatedBinary(r, m));
33+
}
34+
}
35+
}
36+
37+
private Bits encodeToStandardBinary(int x, int len) {
38+
return encodeToBinary(x, len);
39+
}
40+
41+
private Bits encodeToTruncatedBinary(int x, int n) {
42+
// Set k = floor(log2(n)), i.e., k such that 2^k <= n < 2^(k+1).
43+
int k = 0, t = n;
44+
while (t > 1) { k++; t >>= 1; }
45+
46+
// Set u to the number of unused codewords = 2^(k+1) - n.
47+
int u = (1 << k+1) - n;
48+
49+
if (x < u) return encodeToBinary(x, k);
50+
else return encodeToBinary(x+u, k+1);
51+
}
52+
53+
private Bits encodeToBinary(int x, int len) {
54+
Bits s = new Bits();
55+
while (x != 0) {
56+
if ((x & 0x01) == 0) s = Bits.ofZero().append(s);
57+
else s = Bits.ofOne().append(s);
58+
x >>= 1;
59+
}
60+
while (s.length() < len) s = Bits.ofZero().append(s);
61+
return s;
62+
}
63+
}

src/test/java/com/github/myibu/algorithm/AlgorithmTest.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import com.github.myibu.algorithm.compress.LZFCompressor;
66
import com.github.myibu.algorithm.data.Bits;
77
import com.github.myibu.algorithm.data.Bytes;
8+
import com.github.myibu.algorithm.endode.Encoder;
9+
import com.github.myibu.algorithm.endode.GolombEncoder;
810
import com.github.myibu.algorithm.filter.*;
911
import com.github.myibu.algorithm.hash.MurmurHash2;
1012
import com.github.myibu.algorithm.hash.SHA256;
@@ -172,4 +174,15 @@ public void testLZ77Compressor() {
172174
Compressor compressor = new LZ77Compressor();
173175
compressor.compress(in_data, in_data.length, out_data);
174176
}
177+
178+
@Test
179+
public void testGolombEncoder() {
180+
int m = 5;
181+
GolombEncoder encoder = new GolombEncoder();
182+
System.out.println(5 + "= " + encoder.encode(5, m));
183+
System.out.println(6 + "= " + encoder.encode(6, m));
184+
System.out.println(7 + "= " + encoder.encode(7, m));
185+
System.out.println(8 + "= " + encoder.encode(8, m));
186+
System.out.println(9 + "= " + encoder.encode(9, m));
187+
}
175188
}

0 commit comments

Comments
 (0)