on 4e46b53 help sign in
bridge/src/nockjs/bits.js
333 lines 6.8 kB history raw
1var noun = require('./noun.js'),
2 BigInteger = require('jsbn').BigInteger,
3 zero = noun.Atom.yes,
4 one = noun.Atom.no;
6// a is native, returns native
7function met(a, b) {
8 var bits = b.number.bitLength(),
9 full = bits >>> a,
10 part = (full << a) !== bits;
12 return part ? full + 1 : full;
15function gth(a, b) {
16 return a.number.compareTo(b.number) > 0;
19function lth(a, b) {
20 return a.number.compareTo(b.number) < 0;
23function gte(a, b) {
24 return a.number.compareTo(b.number) >= 0;
27function lte(a, b) {
28 return a.number.compareTo(b.number) <= 0;
31function add(a, b) {
32 return new noun.Atom.Atom(a.number.add(b.number));
35function dec(a) {
36 return sub(a, one);
39function bex(a) {
40 return new noun.Atom.Atom(BigInteger.ONE.shiftLeft(a.number.intValue()));
43function sub(a, b) {
44 var r = a.number.subtract(b.number);
45 if ( r.signum < 0 ) {
46 throw new Error("subtract underflow");
47 }
48 else {
49 return new noun.Atom.Atom(r);
50 }
53function lsh(a, b, c) {
54 var bits = b.number.shiftLeft(a.number.intValue()).intValue();
55 return new noun.Atom.Atom(c.number.shiftLeft(bits));
58function rsh(a, b, c) {
59 var bits = b.number.shiftLeft(a.number.intValue()).intValue();
60 return new noun.Atom.Atom(c.number.shiftRight(bits));
63// to/from little-endian 32-bit word array, as used in vere
64// TODO: efficiency is horrible here, but can be improved using internals
65function bytesToWords(bytes) {
66 var len = bytes.length,
67 trim = len % 4;
68 var i, b, w;
70 if ( trim > 0 ) {
71 len += (4-trim);
72 for ( i = 0; i < trim; ++i ) {
73 bytes.push(0);
74 }
75 }
77 var size = len >> 2;
78 var words = new Array(size);
79 for ( i = 0, b = 0; i < size; ++i ) {
80 w = (bytes[b++] << 0) & 0x000000FF;
81 w ^= (bytes[b++] << 8) & 0x0000FF00;
82 w ^= (bytes[b++] << 16) & 0x00FF0000;
83 w ^= (bytes[b++] << 24) & 0xFF000000;
84 words[i] = w;
85 }
86 return words;
87};
89function wordsToBytes(words) {
90 var buf = [];
91 var w, i, b;
92 for ( i = 0, b = 0; i < words.length; ++i ) {
93 w = words[i];
94 buf[b++] = 0xff & (w & 0x000000FF);
95 buf[b++] = 0xff & ((w & 0x0000FF00) >>> 8);
96 buf[b++] = 0xff & ((w & 0x00FF0000) >>> 16);
97 buf[b++] = 0xff & ((w & 0xFF000000) >>> 24);
98 }
99 // or here. one of the 'get rid of extra zeros' functions.
100 while ( buf[--b] === 0 ) {
101 buf.pop();
102 }
103 return buf;
104};
106function bytesToAtom(bytes) {
107 var byt, parts = [];
108 for ( var i = bytes.length - 1; i >= 0; --i ) {
109 byt = bytes[i] & 0xff;
110 parts.push(byt < 16 ? ("0" + byt.toString(16)) : byt.toString(16));
111 }
112 return new noun.Atom.Atom(new BigInteger(parts.join(''), 16));
115function atomToBytes(atom) {
116 return atom.bytes();
119function atomToWords(atom) {
120 return bytesToWords(atomToBytes(atom));
123function wordsToAtom(words) {
124 return bytesToAtom(wordsToBytes(words));
127var malt = wordsToAtom;
129// XX: INTERNAL
130function slaq(bloq, len) {
131 return new Array(((len << bloq) + 31) >>> 5);
134// src is atom, all others native
135function chop(met, fum, wid, tou, dst, src) {
136 var buf = atomToWords(src),
137 len = buf.length,
138 i, j, mek, baf, bat, hut, san,
139 wuf, wut, waf, raf, wat, rat, hop;
141 if ( met < 5 ) {
142 san = 1 << met;
143 mek = ((1 << san) - 1);
144 baf = fum << met;
145 bat = tou << met;
147 for ( i = 0; i < wid; ++i ) {
148 waf = baf >>> 5;
149 raf = baf & 31;
150 wat = bat >>> 5;
151 rat = bat & 31;
152 hop = ((waf >= len) ? 0 : buf[waf]);
153 hop = ((hop >>> raf) & mek);
154 dst[wat] ^= hop << rat;
155 baf += san;
156 bat += san;
157 }
158 }
159 else {
160 hut = met - 5;
161 san = 1 << hut;
163 for ( i = 0; i < wid; ++i ) {
164 wuf = (fum + i) << hut;
165 wut = (tou + i) << hut;
167 for ( j = 0; j < san; ++j ) {
168 dst[wut + j] ^= ((wuf + j) >= len)
169 ? 0
170 : buf[wuf + j];
171 }
172 }
173 }
176function cut(a, b, c, d) {
177 var ai = a.number.intValue(),
178 bi = b.number.intValue(),
179 ci = c.number.intValue();
181 var len = met(ai, d);
182 if ( zero.equals(c) || bi >= len ) {
183 return zero;
184 }
185 if ( bi + ci > len ) {
186 ci = len - b;
187 }
188 if ( 0 === bi && ci === len ) {
189 return d;
190 }
191 else {
192 var sal = slaq(ai, ci);
193 chop(ai, bi, ci, 0, sal, d);
194 return malt(sal);
195 }
198var maxCat = noun.Atom.fromInt(0xffffffff);
199var catBits = noun.Atom.fromInt(32);
201function end(a, b, c) {
202 if ( gth(a, catBits) ) {
203 throw new Error("Fail");
204 }
205 else if ( gth(b, maxCat) ) {
206 return c;
207 }
208 else {
209 var ai = a.number.intValue(),
210 bi = b.number.intValue(),
211 len = met(ai, c);
213 if ( 0 === bi ) {
214 return zero;
215 }
216 else if ( bi >= len ) {
217 return c;
218 }
219 else {
220 var sal = slaq(ai, bi);
221 chop(ai, 0, bi, 0, sal, c);
222 return malt(sal);
223 }
224 }
227function mix(a, b) {
228 return new noun.Atom.Atom(a.number.xor(b.number));
231function cat(a, b, c) {
232 if ( gth(a, catBits) ) {
233 throw new Error("Fail");
234 }
235 else {
236 var ai = a.number.intValue(),
237 lew = met(ai, b),
238 ler = met(ai, c),
239 all = lew + ler;
241 if ( 0 === all ) {
242 return zero;
243 }
244 else {
245 var sal = slaq(ai, all);
246 chop(ai, 0, lew, 0, sal, b);
247 chop(ai, 0, ler, lew, sal, c);
248 return malt(sal);
249 }
250 }
253function can(a, b) {
254 if ( gth(a, catBits) ) {
255 throw new Error("Fail");
256 }
257 else {
258 var ai = a.number.intValue(),
259 tot = 0,
260 cab = b,
261 pos, i_cab, pi_cab, qi_cab;
263 // measure
264 while ( true ) {
265 if ( zero.equals(cab) ) {
266 break;
267 }
268 if ( !cab.deep ) {
269 throw new Error("Fail");
270 }
271 i_cab = cab.head;
272 if ( !i_cab.deep ) {
273 throw new Error("Fail");
274 }
275 pi_cab = i_cab.head;
276 qi_cab = i_cab.tail;
277 if ( gth(pi_cab, maxCat) ) {
278 throw new Error("Fail");
279 }
280 if ( qi_cab.deep ) {
281 throw new Error("Fail");
282 }
283 if ( (tot + pi_cab) < tot ) {
284 throw new Error("Fail");
285 }
286 tot += pi_cab;
287 cab = cab.tail;
288 }
289 if ( 0 === tot ) {
290 return zero;
291 }
292 var sal = slaq(ai, tot);
294 // chop the list atoms in
295 cab = b;
296 pos = 0;
297 while ( !zero.equals(cab) ) {
298 i_cab = cab.head;
299 pi_cab = i_cab.head.number.intValue();
300 qi_cab = i_cab.tail;
302 chop(ai, 0, pi_cab, pos, sal, qi_cab);
303 pos += pi_cab;
304 cab = cab.tail;
305 }
306 return malt(sal);
307 }
310module.exports = {
311 met: met,
312 cut: cut,
313 add: add,
314 sub: sub,
315 dec: dec,
316 gth: gth,
317 lth: lth,
318 gte: gte,
319 lte: lte,
320 bex: bex,
321 lsh: lsh,
322 rsh: rsh,
323 end: end,
324 mix: mix,
325 cat: cat,
326 can: can,
327 bytesToWords: bytesToWords,
328 wordsToBytes: wordsToBytes,
329 bytesToAtom: bytesToAtom,
330 atomToBytes: atomToBytes,
331 atomToWords: atomToWords,
332 wordsToAtom: wordsToAtom,
333};