11package com .github .myibu .algorithm .endode ;
22
3+ import com .github .myibu .algorithm .data .Bit ;
34import com .github .myibu .algorithm .data .Bits ;
45
56/**
1011 */
1112public class GolombEncoder implements Encoder {
1213 /**
13- *
14+ * encode n to binary bits based on argument m
1415 * @param n the value to encode
1516 * @param m m, like 5
1617 * @return the length of encoded bits
@@ -23,7 +24,7 @@ public Bits encode(int n, int m) {
2324 int r = n % m ;
2425 int k = (int )(Math .ceil (Math .log (m ) / Math .log (2 )));
2526 if ((m & 0x01 ) == 0 ) {
26- return bits .append (encodeToStandardBinary (r , k ));
27+ return bits .append (encodeToBinary (r , k ));
2728 } else {
2829 // truncated binary encoding
2930 if (r < Math .pow (2 , k ) - m ) {
@@ -34,10 +35,6 @@ public Bits encode(int n, int m) {
3435 }
3536 }
3637
37- private Bits encodeToStandardBinary (int x , int len ) {
38- return encodeToBinary (x , len );
39- }
40-
4138 private Bits encodeToTruncatedBinary (int x , int n ) {
4239 // Set k = floor(log2(n)), i.e., k such that 2^k <= n < 2^(k+1).
4340 int k = 0 , t = n ;
@@ -60,4 +57,55 @@ private Bits encodeToBinary(int x, int len) {
6057 while (s .length () < len ) s = Bits .ofZero ().append (s );
6158 return s ;
6259 }
60+
61+ /**
62+ * decode binary bits to n
63+ * @param bits encoded binary bits
64+ * @param m m, like 5
65+ * @return decoded value
66+ */
67+ public int decode (Bits bits , int m ) {
68+ // To decode, read the first k bits.
69+ // If they encode a value less than u, decoding is complete.
70+ // Otherwise, read an additional bit and subtract u from the result.
71+ boolean isRStart = false ;
72+ Bits qb = new Bits (), rb = new Bits ();
73+ for (Bit bit : bits ) {
74+ if (!isRStart && bit == Bit .ZERO ) {
75+ isRStart = true ;
76+ continue ;
77+ }
78+ if (!isRStart ) {
79+ qb .append (bit );
80+ } else {
81+ rb .append (bit );
82+ }
83+ }
84+ int q = qb .length ();
85+ int r = 0 ;
86+ if ((m & 0x01 ) == 0 ) {
87+ r = encodeToBinary (rb );
88+ } else {
89+ r = decodeTruncatedBinary (rb , m );
90+ }
91+ return q * m + r ;
92+ }
93+
94+ public int decodeTruncatedBinary (Bits bits , int m ) {
95+ // Set k = floor(log2(n)), i.e., k such that 2^k <= n < 2^(k+1).
96+ int k = 0 , t = m ;
97+ while (t > 1 ) { k ++; t >>= 1 ; }
98+ // Set u to the number of unused codewords = 2^(k+1) - n.
99+ int u = (1 << k +1 ) - m ;
100+ int x = encodeToBinary (bits );
101+ return (x < u ) ? x : (x - u );
102+ }
103+
104+ private int encodeToBinary (Bits bits ) {
105+ int x = 0 ;
106+ for (int i = 0 ; i < bits .length (); i ++) {
107+ x += (bits .get (i ).value () << (bits .length () - i - 1 ));
108+ }
109+ return x ;
110+ }
63111}
0 commit comments