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