-
Notifications
You must be signed in to change notification settings - Fork 20
/
bitEncoder.js
96 lines (82 loc) · 2.27 KB
/
bitEncoder.js
1
2
3
4
5
6
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
function BitEncoder() {
var kNumBitModelTotalBits = 11;
var kBitModelTotal = 1 << kNumBitModelTotalBits;
var kNumMoveBits = 5;
var kNumMoveReducingBits = 2;
var kNumBitPriceShiftBits = 6;
var prob;
this.init = function() {
prob = kBitModelTotal >> 1;
};
this.updateModel = function(symbol) {
if (symbol === 0) {
prob += (kBitModelTotal - prob) >>> kNumMoveBits;
} else {
prob -= prob >>> kNumMoveBits;
}
};
this.encode = function(encoder, symbol) {
encoder.encodeBit(prob, kNumBitModelTotalBits, symbol);
this.updateModel(symbol);
};
this.getPrice = function(symbol) {
var priceIndex = ((prob - symbol) ^ (-symbol)) & (kBitModelTotal - 1);
return this.probPrices[priceIndex >>> kNumMoveReducingBits];
};
this.initializeProbPrices = function() {
var kNumBits = kNumBitModelTotalBits - kNumMoveReducingBits;
var i, j;
for (i = kNumBits - 1; i >= 0; i--) {
var start = 1 << (kNumBits - i - 1);
var end = 1 << (kNumBits - i);
for (j = start; j < end; j++) {
this.probPrices[j] = (i << kNumBitPriceShiftBits) +
(((end - j) << kNumBitPriceShiftBits) >>> (kNumBits - i - 1));
}
}
};
// TODO: make this statically initialized
if (this.probPrices.length === 0) {
this.initializeProbPrices();
}
}
BitEncoder.prototype.probPrices = [];
function BitTreeEncoder(numBitLevels) {
this.models = [];
this.init = function() {
var i;
for (i = 1; i < (1 << numBitLevels); i++) {
this.models[i] = new BitEncoder();
this.models[i].init();
}
};
this.encode = function(rangeEncoder, symbol) {
var m = 1, bitIndex;
for (bitIndex = numBitLevels - 1; bitIndex >= 0; bitIndex--) {
var bit = (symbol >>> bitIndex) & 1;
this.models[m].encode(rangeEncoder, bit);
m = (m << 1) | bit;
}
};
this.reverseEncode = function(rangeEncoder, symbol) {
var m = 1, i;
for (i = 0; i < numBitLevels; i++) {
var bit = symbol & 1;
this.models[m].encode(rangeEncoder, bit);
m = (m << 1) | bit;
symbol >>>= 1;
}
};
this.getPrice = function(symbol) {
var price = 0, m = 1, i;
for (i = numBitLevels; i > 0; i--) {
var bit = symbol & 1;
symbol >>>= 1;
price += this.models[m].getPrice(bit);
m = (m << 1) | bit;
}
return price;
};
}
exports.BitTreeEncoder = BitTreeEncoder;
exports.BitEncoder = BitEncoder;