-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathrangeCoder.js
114 lines (98 loc) · 2.05 KB
/
rangeCoder.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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
var kTopValue = 1 << 24, kBotValue = 1 << 16;
function shiftLeft8(v) {
v <<= 8;
return v >= 0 ? v : v + 0x100000000;
}
function Encoder() {
var low, range, cacheSize, cache;
this.bytes = [];
var init = function() {
low = 0;
range = 0xFFFFFFFF;
cacheSize = 1;
cache = 0;
this.bytes = [];
};
init();
this.init = init;
this.encode = function(start, size, total) {
range = (range / total) | 0;
low += start * range;
range *= size;
while (range < kTopValue) {
range = shiftLeft8(range);
this.shiftLow();
}
};
this.shiftLow = function() {
var overflow = low > 0xFFFFFFFF;
if (low < 0xFF000000 || overflow) {
var temp = cache;
do {
this.bytes[this.bytes.length] = (temp + (overflow ? 1 : 0)) & 0xFF;
temp = 0xFF;
} while (--cacheSize !== 0);
cache = low >>> 24;
}
cacheSize++;
low = shiftLeft8(low);
};
this.finish = function() {
var i;
for (i = 0; i < 5; i++) {
this.shiftLow();
}
};
this.encodeBit = function(size, numTotalBits, symbol) {
var newBound = (range >>> numTotalBits) * size;
if (symbol === 0) {
range = newBound;
} else {
low += newBound;
range -= newBound;
}
while (range < kTopValue) {
range = shiftLeft8(range);
this.shiftLow();
}
};
/*
this.encodeDirectBits(v, numTotalBits) {
for (var i = numTotalBits - 1; i != 0; i--) {
range >>= 1;
if (((v >> i) & 1) == 1)
low += range;
if (range < kTopValue) {
range <<= 8;
this.shiftLow();
}
}
};
*/
}
function Decoder(bytes) {
var code = 0, range = 0xFFFFFFFF;
var at = 0;
var i;
this.bytes = bytes;
for (i = 0; i < 5; i++) {
code = (code << 8) | this.bytes[at++];
}
this.normalize = function() {
while (range < kTopValue) {
code = shiftLeft8(code) | this.bytes[at++];
range = shiftLeft8(range);
}
};
this.getThreshold = function(total) {
range = (range / total) | 0;
return (code / range) | 0;
};
this.decode = function(start, size, total) {
code -= start * range;
range *= size;
this.normalize();
};
}
exports.Encoder = Encoder;
exports.Decoder = Decoder;