├── Readme.md ├── examples └── example.js ├── index.js ├── lib ├── jsbn.js ├── server.js └── snowflake.js └── package.json /Readme.md: -------------------------------------------------------------------------------- 1 | node-snowflake 2 | ============== 3 | 4 | node-snowflake is a node.js clone for [twitter snowflake](https://github.com/twitter/snowflake). 5 | 6 | ###how to use 7 | 8 | >//only run simple http server
9 | > require('node-snowflake').Server(3001);

10 | >//request url example:GET http://localhost:3001/next_id?worker_id={optional}&data_center_id={optional}&sequence={optional}

11 | >//response : {"id":"439658373735124992"} 12 |
13 | 14 | -------------------------- 15 | 16 | >//only run snowflake nextId
17 | >var snowflake = require('node-snowflake').Snowflake;
18 | >var id = snowflake.nextId(); // use default set
19 | >//or
20 | >//snowflake.init({worker_id : 1, data_center_id : 1, sequence : 0});
21 | >//var id = snowflake.nextId();
22 | >console.log(id); 23 |
24 | 25 | 26 | ###see examples/example.js -------------------------------------------------------------------------------- /examples/example.js: -------------------------------------------------------------------------------- 1 | //only run simple http server 2 | require('../').Server(); 3 | 4 | /***************************************************/ 5 | //only run snowflake nextId 6 | // var snowflake = require('../').Snowflake; 7 | // console.log(snowflake.nextId()); -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | exports.Server = require('./lib/server'); 2 | exports.Snowflake = require('./lib/snowflake'); -------------------------------------------------------------------------------- /lib/jsbn.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2005 Tom Wu 2 | // All Rights Reserved. 3 | // See "LICENSE" for details. 4 | 5 | // Basic JavaScript BN library - subset useful for RSA encryption. 6 | 7 | // Bits per digit 8 | var dbits; 9 | 10 | // JavaScript engine analysis 11 | var canary = 0xdeadbeefcafe; 12 | var j_lm = ((canary&0xffffff)==0xefcafe); 13 | 14 | // (public) Constructor 15 | function BigInteger(a,b,c) { 16 | if(a != null) 17 | if("number" == typeof a) this.fromNumber(a,b,c); 18 | else if(b == null && "string" != typeof a) this.fromString(a,256); 19 | else this.fromString(a,b); 20 | } 21 | 22 | // return new, unset BigInteger 23 | function nbi() { return new BigInteger(null); } 24 | 25 | // am: Compute w_j += (x*this_i), propagate carries, 26 | // c is initial carry, returns final carry. 27 | // c < 3*dvalue, x < 2*dvalue, this_i < dvalue 28 | // We need to select the fastest one that works in this environment. 29 | 30 | // am1: use a single mult and divide to get the high bits, 31 | // max digit bits should be 26 because 32 | // max internal value = 2*dvalue^2-2*dvalue (< 2^53) 33 | function am1(i,x,w,j,c,n) { 34 | while(--n >= 0) { 35 | var v = x*this[i++]+w[j]+c; 36 | c = Math.floor(v/0x4000000); 37 | w[j++] = v&0x3ffffff; 38 | } 39 | return c; 40 | } 41 | // am2 avoids a big mult-and-extract completely. 42 | // Max digit bits should be <= 30 because we do bitwise ops 43 | // on values up to 2*hdvalue^2-hdvalue-1 (< 2^31) 44 | function am2(i,x,w,j,c,n) { 45 | var xl = x&0x7fff, xh = x>>15; 46 | while(--n >= 0) { 47 | var l = this[i]&0x7fff; 48 | var h = this[i++]>>15; 49 | var m = xh*l+h*xl; 50 | l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff); 51 | c = (l>>>30)+(m>>>15)+xh*h+(c>>>30); 52 | w[j++] = l&0x3fffffff; 53 | } 54 | return c; 55 | } 56 | // Alternately, set max digit bits to 28 since some 57 | // browsers slow down when dealing with 32-bit numbers. 58 | function am3(i,x,w,j,c,n) { 59 | var xl = x&0x3fff, xh = x>>14; 60 | while(--n >= 0) { 61 | var l = this[i]&0x3fff; 62 | var h = this[i++]>>14; 63 | var m = xh*l+h*xl; 64 | l = xl*l+((m&0x3fff)<<14)+w[j]+c; 65 | c = (l>>28)+(m>>14)+xh*h; 66 | w[j++] = l&0xfffffff; 67 | } 68 | return c; 69 | } 70 | //if(j_lm && (navigator.appName == "Microsoft Internet Explorer")) { 71 | // BigInteger.prototype.am = am2; 72 | // dbits = 30; 73 | //} 74 | //else if(j_lm && (navigator.appName != "Netscape")) { 75 | // BigInteger.prototype.am = am1; 76 | // dbits = 26; 77 | //} 78 | //else { // Mozilla/Netscape seems to prefer am3 79 | BigInteger.prototype.am = am3; 80 | dbits = 28; 81 | //} 82 | 83 | BigInteger.prototype.DB = dbits; 84 | BigInteger.prototype.DM = ((1<= 0; --i) r[i] = this[i]; 112 | r.t = this.t; 113 | r.s = this.s; 114 | } 115 | 116 | // (protected) set from integer value x, -DV <= x < DV 117 | function bnpFromInt(x) { 118 | this.t = 1; 119 | this.s = (x<0)?-1:0; 120 | if(x > 0) this[0] = x; 121 | else if(x < -1) this[0] = x+this.DV; 122 | else this.t = 0; 123 | } 124 | 125 | // return bigint initialized to value 126 | function nbv(i) { var r = nbi(); r.fromInt(i); return r; } 127 | 128 | // (protected) set from string and radix 129 | function bnpFromString(s,b) { 130 | var k; 131 | if(b == 16) k = 4; 132 | else if(b == 8) k = 3; 133 | else if(b == 256) k = 8; // byte array 134 | else if(b == 2) k = 1; 135 | else if(b == 32) k = 5; 136 | else if(b == 4) k = 2; 137 | else { this.fromRadix(s,b); return; } 138 | this.t = 0; 139 | this.s = 0; 140 | var i = s.length, mi = false, sh = 0; 141 | while(--i >= 0) { 142 | var x = (k==8)?s[i]&0xff:intAt(s,i); 143 | if(x < 0) { 144 | if(s.charAt(i) == "-") mi = true; 145 | continue; 146 | } 147 | mi = false; 148 | if(sh == 0) 149 | this[this.t++] = x; 150 | else if(sh+k > this.DB) { 151 | this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<>(this.DB-sh)); 153 | } 154 | else 155 | this[this.t-1] |= x<= this.DB) sh -= this.DB; 158 | } 159 | if(k == 8 && (s[0]&0x80) != 0) { 160 | this.s = -1; 161 | if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)< 0 && this[this.t-1] == c) --this.t; 171 | } 172 | 173 | // (public) return string representation in given radix 174 | function bnToString(b) { 175 | if(this.s < 0) return "-"+this.negate().toString(b); 176 | var k; 177 | if(b == 16) k = 4; 178 | else if(b == 8) k = 3; 179 | else if(b == 2) k = 1; 180 | else if(b == 32) k = 5; 181 | else if(b == 4) k = 2; 182 | else return this.toRadix(b); 183 | var km = (1< 0) { 186 | if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); } 187 | while(i >= 0) { 188 | if(p < k) { 189 | d = (this[i]&((1<>(p+=this.DB-k); 191 | } 192 | else { 193 | d = (this[i]>>(p-=k))&km; 194 | if(p <= 0) { p += this.DB; --i; } 195 | } 196 | if(d > 0) m = true; 197 | if(m) r += int2char(d); 198 | } 199 | } 200 | return m?r:"0"; 201 | } 202 | 203 | // (public) -this 204 | function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; } 205 | 206 | // (public) |this| 207 | function bnAbs() { return (this.s<0)?this.negate():this; } 208 | 209 | // (public) return + if this > a, - if this < a, 0 if equal 210 | function bnCompareTo(a) { 211 | var r = this.s-a.s; 212 | if(r != 0) return r; 213 | var i = this.t; 214 | r = i-a.t; 215 | if(r != 0) return (this.s<0)?-r:r; 216 | while(--i >= 0) if((r=this[i]-a[i]) != 0) return r; 217 | return 0; 218 | } 219 | 220 | // returns bit length of the integer x 221 | function nbits(x) { 222 | var r = 1, t; 223 | if((t=x>>>16) != 0) { x = t; r += 16; } 224 | if((t=x>>8) != 0) { x = t; r += 8; } 225 | if((t=x>>4) != 0) { x = t; r += 4; } 226 | if((t=x>>2) != 0) { x = t; r += 2; } 227 | if((t=x>>1) != 0) { x = t; r += 1; } 228 | return r; 229 | } 230 | 231 | // (public) return the number of bits in "this" 232 | function bnBitLength() { 233 | if(this.t <= 0) return 0; 234 | return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM)); 235 | } 236 | 237 | // (protected) r = this << n*DB 238 | function bnpDLShiftTo(n,r) { 239 | var i; 240 | for(i = this.t-1; i >= 0; --i) r[i+n] = this[i]; 241 | for(i = n-1; i >= 0; --i) r[i] = 0; 242 | r.t = this.t+n; 243 | r.s = this.s; 244 | } 245 | 246 | // (protected) r = this >> n*DB 247 | function bnpDRShiftTo(n,r) { 248 | for(var i = n; i < this.t; ++i) r[i-n] = this[i]; 249 | r.t = Math.max(this.t-n,0); 250 | r.s = this.s; 251 | } 252 | 253 | // (protected) r = this << n 254 | function bnpLShiftTo(n,r) { 255 | var bs = n%this.DB; 256 | var cbs = this.DB-bs; 257 | var bm = (1<= 0; --i) { 260 | r[i+ds+1] = (this[i]>>cbs)|c; 261 | c = (this[i]&bm)<= 0; --i) r[i] = 0; 264 | r[ds] = c; 265 | r.t = this.t+ds+1; 266 | r.s = this.s; 267 | r.clamp(); 268 | } 269 | 270 | // (protected) r = this >> n 271 | function bnpRShiftTo(n,r) { 272 | r.s = this.s; 273 | var ds = Math.floor(n/this.DB); 274 | if(ds >= this.t) { r.t = 0; return; } 275 | var bs = n%this.DB; 276 | var cbs = this.DB-bs; 277 | var bm = (1<>bs; 279 | for(var i = ds+1; i < this.t; ++i) { 280 | r[i-ds-1] |= (this[i]&bm)<>bs; 282 | } 283 | if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<>= this.DB; 295 | } 296 | if(a.t < this.t) { 297 | c -= a.s; 298 | while(i < this.t) { 299 | c += this[i]; 300 | r[i++] = c&this.DM; 301 | c >>= this.DB; 302 | } 303 | c += this.s; 304 | } 305 | else { 306 | c += this.s; 307 | while(i < a.t) { 308 | c -= a[i]; 309 | r[i++] = c&this.DM; 310 | c >>= this.DB; 311 | } 312 | c -= a.s; 313 | } 314 | r.s = (c<0)?-1:0; 315 | if(c < -1) r[i++] = this.DV+c; 316 | else if(c > 0) r[i++] = c; 317 | r.t = i; 318 | r.clamp(); 319 | } 320 | 321 | // (protected) r = this * a, r != this,a (HAC 14.12) 322 | // "this" should be the larger one if appropriate. 323 | function bnpMultiplyTo(a,r) { 324 | var x = this.abs(), y = a.abs(); 325 | var i = x.t; 326 | r.t = i+y.t; 327 | while(--i >= 0) r[i] = 0; 328 | for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t); 329 | r.s = 0; 330 | r.clamp(); 331 | if(this.s != a.s) BigInteger.ZERO.subTo(r,r); 332 | } 333 | 334 | // (protected) r = this^2, r != this (HAC 14.16) 335 | function bnpSquareTo(r) { 336 | var x = this.abs(); 337 | var i = r.t = 2*x.t; 338 | while(--i >= 0) r[i] = 0; 339 | for(i = 0; i < x.t-1; ++i) { 340 | var c = x.am(i,x[i],r,2*i,0,1); 341 | if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) { 342 | r[i+x.t] -= x.DV; 343 | r[i+x.t+1] = 1; 344 | } 345 | } 346 | if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1); 347 | r.s = 0; 348 | r.clamp(); 349 | } 350 | 351 | // (protected) divide this by m, quotient and remainder to q, r (HAC 14.20) 352 | // r != q, this != m. q or r may be null. 353 | function bnpDivRemTo(m,q,r) { 354 | var pm = m.abs(); 355 | if(pm.t <= 0) return; 356 | var pt = this.abs(); 357 | if(pt.t < pm.t) { 358 | if(q != null) q.fromInt(0); 359 | if(r != null) this.copyTo(r); 360 | return; 361 | } 362 | if(r == null) r = nbi(); 363 | var y = nbi(), ts = this.s, ms = m.s; 364 | var nsh = this.DB-nbits(pm[pm.t-1]); // normalize modulus 365 | if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); } 366 | else { pm.copyTo(y); pt.copyTo(r); } 367 | var ys = y.t; 368 | var y0 = y[ys-1]; 369 | if(y0 == 0) return; 370 | var yt = y0*(1<1)?y[ys-2]>>this.F2:0); 371 | var d1 = this.FV/yt, d2 = (1<= 0) { 375 | r[r.t++] = 1; 376 | r.subTo(t,r); 377 | } 378 | BigInteger.ONE.dlShiftTo(ys,t); 379 | t.subTo(y,y); // "negative" y so we can replace sub with am later 380 | while(y.t < ys) y[y.t++] = 0; 381 | while(--j >= 0) { 382 | // Estimate quotient digit 383 | var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2); 384 | if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out 385 | y.dlShiftTo(j,t); 386 | r.subTo(t,r); 387 | while(r[i] < --qd) r.subTo(t,r); 388 | } 389 | } 390 | if(q != null) { 391 | r.drShiftTo(ys,q); 392 | if(ts != ms) BigInteger.ZERO.subTo(q,q); 393 | } 394 | r.t = ys; 395 | r.clamp(); 396 | if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder 397 | if(ts < 0) BigInteger.ZERO.subTo(r,r); 398 | } 399 | 400 | // (public) this mod a 401 | function bnMod(a) { 402 | var r = nbi(); 403 | this.abs().divRemTo(a,null,r); 404 | if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r); 405 | return r; 406 | } 407 | 408 | // Modular reduction using "classic" algorithm 409 | function Classic(m) { this.m = m; } 410 | function cConvert(x) { 411 | if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m); 412 | else return x; 413 | } 414 | function cRevert(x) { return x; } 415 | function cReduce(x) { x.divRemTo(this.m,null,x); } 416 | function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } 417 | function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); } 418 | 419 | Classic.prototype.convert = cConvert; 420 | Classic.prototype.revert = cRevert; 421 | Classic.prototype.reduce = cReduce; 422 | Classic.prototype.mulTo = cMulTo; 423 | Classic.prototype.sqrTo = cSqrTo; 424 | 425 | // (protected) return "-1/this % 2^DB"; useful for Mont. reduction 426 | // justification: 427 | // xy == 1 (mod m) 428 | // xy = 1+km 429 | // xy(2-xy) = (1+km)(1-km) 430 | // x[y(2-xy)] = 1-k^2m^2 431 | // x[y(2-xy)] == 1 (mod m^2) 432 | // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2 433 | // should reduce x and y(2-xy) by m^2 at each step to keep size bounded. 434 | // JS multiply "overflows" differently from C/C++, so care is needed here. 435 | function bnpInvDigit() { 436 | if(this.t < 1) return 0; 437 | var x = this[0]; 438 | if((x&1) == 0) return 0; 439 | var y = x&3; // y == 1/x mod 2^2 440 | y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4 441 | y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8 442 | y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16 443 | // last step - calculate inverse mod DV directly; 444 | // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints 445 | y = (y*(2-x*y%this.DV))%this.DV; // y == 1/x mod 2^dbits 446 | // we really want the negative inverse, and -DV < y < DV 447 | return (y>0)?this.DV-y:-y; 448 | } 449 | 450 | // Montgomery reduction 451 | function Montgomery(m) { 452 | this.m = m; 453 | this.mp = m.invDigit(); 454 | this.mpl = this.mp&0x7fff; 455 | this.mph = this.mp>>15; 456 | this.um = (1<<(m.DB-15))-1; 457 | this.mt2 = 2*m.t; 458 | } 459 | 460 | // xR mod m 461 | function montConvert(x) { 462 | var r = nbi(); 463 | x.abs().dlShiftTo(this.m.t,r); 464 | r.divRemTo(this.m,null,r); 465 | if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r); 466 | return r; 467 | } 468 | 469 | // x/R mod m 470 | function montRevert(x) { 471 | var r = nbi(); 472 | x.copyTo(r); 473 | this.reduce(r); 474 | return r; 475 | } 476 | 477 | // x = x/R mod m (HAC 14.32) 478 | function montReduce(x) { 479 | while(x.t <= this.mt2) // pad x so am has enough room later 480 | x[x.t++] = 0; 481 | for(var i = 0; i < this.m.t; ++i) { 482 | // faster way of calculating u0 = x[i]*mp mod DV 483 | var j = x[i]&0x7fff; 484 | var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM; 485 | // use am to combine the multiply-shift-add into one call 486 | j = i+this.m.t; 487 | x[j] += this.m.am(0,u0,x,i,0,this.m.t); 488 | // propagate carry 489 | while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; } 490 | } 491 | x.clamp(); 492 | x.drShiftTo(this.m.t,x); 493 | if(x.compareTo(this.m) >= 0) x.subTo(this.m,x); 494 | } 495 | 496 | // r = "x^2/R mod m"; x != r 497 | function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); } 498 | 499 | // r = "xy/R mod m"; x,y != r 500 | function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } 501 | 502 | Montgomery.prototype.convert = montConvert; 503 | Montgomery.prototype.revert = montRevert; 504 | Montgomery.prototype.reduce = montReduce; 505 | Montgomery.prototype.mulTo = montMulTo; 506 | Montgomery.prototype.sqrTo = montSqrTo; 507 | 508 | // (protected) true iff this is even 509 | function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; } 510 | 511 | // (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79) 512 | function bnpExp(e,z) { 513 | if(e > 0xffffffff || e < 1) return BigInteger.ONE; 514 | var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1; 515 | g.copyTo(r); 516 | while(--i >= 0) { 517 | z.sqrTo(r,r2); 518 | if((e&(1< 0) z.mulTo(r2,g,r); 519 | else { var t = r; r = r2; r2 = t; } 520 | } 521 | return z.revert(r); 522 | } 523 | 524 | // (public) this^e % m, 0 <= e < 2^32 525 | function bnModPowInt(e,m) { 526 | var z; 527 | if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m); 528 | return this.exp(e,z); 529 | } 530 | 531 | // protected 532 | BigInteger.prototype.copyTo = bnpCopyTo; 533 | BigInteger.prototype.fromInt = bnpFromInt; 534 | BigInteger.prototype.fromString = bnpFromString; 535 | BigInteger.prototype.clamp = bnpClamp; 536 | BigInteger.prototype.dlShiftTo = bnpDLShiftTo; 537 | BigInteger.prototype.drShiftTo = bnpDRShiftTo; 538 | BigInteger.prototype.lShiftTo = bnpLShiftTo; 539 | BigInteger.prototype.rShiftTo = bnpRShiftTo; 540 | BigInteger.prototype.subTo = bnpSubTo; 541 | BigInteger.prototype.multiplyTo = bnpMultiplyTo; 542 | BigInteger.prototype.squareTo = bnpSquareTo; 543 | BigInteger.prototype.divRemTo = bnpDivRemTo; 544 | BigInteger.prototype.invDigit = bnpInvDigit; 545 | BigInteger.prototype.isEven = bnpIsEven; 546 | BigInteger.prototype.exp = bnpExp; 547 | 548 | // public 549 | BigInteger.prototype.toString = bnToString; 550 | BigInteger.prototype.negate = bnNegate; 551 | BigInteger.prototype.abs = bnAbs; 552 | BigInteger.prototype.compareTo = bnCompareTo; 553 | BigInteger.prototype.bitLength = bnBitLength; 554 | BigInteger.prototype.mod = bnMod; 555 | BigInteger.prototype.modPowInt = bnModPowInt; 556 | 557 | // "constants" 558 | BigInteger.ZERO = nbv(0); 559 | BigInteger.ONE = nbv(1); 560 | 561 | // Copyright (c) 2005-2009 Tom Wu 562 | // All Rights Reserved. 563 | // See "LICENSE" for details. 564 | 565 | // Extended JavaScript BN functions, required for RSA private ops. 566 | 567 | // Version 1.1: new BigInteger("0", 10) returns "proper" zero 568 | // Version 1.2: square() API, isProbablePrime fix 569 | 570 | // (public) 571 | function bnClone() { var r = nbi(); this.copyTo(r); return r; } 572 | 573 | // (public) return value as integer 574 | function bnIntValue() { 575 | if(this.s < 0) { 576 | if(this.t == 1) return this[0]-this.DV; 577 | else if(this.t == 0) return -1; 578 | } 579 | else if(this.t == 1) return this[0]; 580 | else if(this.t == 0) return 0; 581 | // assumes 16 < DB < 32 582 | return ((this[1]&((1<<(32-this.DB))-1))<>24; } 587 | 588 | // (public) return value as short (assumes DB>=16) 589 | function bnShortValue() { return (this.t==0)?this.s:(this[0]<<16)>>16; } 590 | 591 | // (protected) return x s.t. r^x < DV 592 | function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); } 593 | 594 | // (public) 0 if this == 0, 1 if this > 0 595 | function bnSigNum() { 596 | if(this.s < 0) return -1; 597 | else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0; 598 | else return 1; 599 | } 600 | 601 | // (protected) convert to radix string 602 | function bnpToRadix(b) { 603 | if(b == null) b = 10; 604 | if(this.signum() == 0 || b < 2 || b > 36) return "0"; 605 | var cs = this.chunkSize(b); 606 | var a = Math.pow(b,cs); 607 | var d = nbv(a), y = nbi(), z = nbi(), r = ""; 608 | this.divRemTo(d,y,z); 609 | while(y.signum() > 0) { 610 | r = (a+z.intValue()).toString(b).substr(1) + r; 611 | y.divRemTo(d,y,z); 612 | } 613 | return z.intValue().toString(b) + r; 614 | } 615 | 616 | // (protected) convert from radix string 617 | function bnpFromRadix(s,b) { 618 | this.fromInt(0); 619 | if(b == null) b = 10; 620 | var cs = this.chunkSize(b); 621 | var d = Math.pow(b,cs), mi = false, j = 0, w = 0; 622 | for(var i = 0; i < s.length; ++i) { 623 | var x = intAt(s,i); 624 | if(x < 0) { 625 | if(s.charAt(i) == "-" && this.signum() == 0) mi = true; 626 | continue; 627 | } 628 | w = b*w+x; 629 | if(++j >= cs) { 630 | this.dMultiply(d); 631 | this.dAddOffset(w,0); 632 | j = 0; 633 | w = 0; 634 | } 635 | } 636 | if(j > 0) { 637 | this.dMultiply(Math.pow(b,j)); 638 | this.dAddOffset(w,0); 639 | } 640 | if(mi) BigInteger.ZERO.subTo(this,this); 641 | } 642 | 643 | // (protected) alternate constructor 644 | function bnpFromNumber(a,b,c) { 645 | if("number" == typeof b) { 646 | // new BigInteger(int,int,RNG) 647 | if(a < 2) this.fromInt(1); 648 | else { 649 | this.fromNumber(a,c); 650 | if(!this.testBit(a-1)) // force MSB set 651 | this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this); 652 | if(this.isEven()) this.dAddOffset(1,0); // force odd 653 | while(!this.isProbablePrime(b)) { 654 | this.dAddOffset(2,0); 655 | if(this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a-1),this); 656 | } 657 | } 658 | } 659 | else { 660 | // new BigInteger(int,RNG) 661 | var x = new Array(), t = a&7; 662 | x.length = (a>>3)+1; 663 | b.nextBytes(x); 664 | if(t > 0) x[0] &= ((1< 0) { 675 | if(p < this.DB && (d = this[i]>>p) != (this.s&this.DM)>>p) 676 | r[k++] = d|(this.s<<(this.DB-p)); 677 | while(i >= 0) { 678 | if(p < 8) { 679 | d = (this[i]&((1<>(p+=this.DB-8); 681 | } 682 | else { 683 | d = (this[i]>>(p-=8))&0xff; 684 | if(p <= 0) { p += this.DB; --i; } 685 | } 686 | if((d&0x80) != 0) d |= -256; 687 | if(k == 0 && (this.s&0x80) != (d&0x80)) ++k; 688 | if(k > 0 || d != this.s) r[k++] = d; 689 | } 690 | } 691 | return r; 692 | } 693 | 694 | function bnEquals(a) { return(this.compareTo(a)==0); } 695 | function bnMin(a) { return(this.compareTo(a)<0)?this:a; } 696 | function bnMax(a) { return(this.compareTo(a)>0)?this:a; } 697 | 698 | // (protected) r = this op a (bitwise) 699 | function bnpBitwiseTo(a,op,r) { 700 | var i, f, m = Math.min(a.t,this.t); 701 | for(i = 0; i < m; ++i) r[i] = op(this[i],a[i]); 702 | if(a.t < this.t) { 703 | f = a.s&this.DM; 704 | for(i = m; i < this.t; ++i) r[i] = op(this[i],f); 705 | r.t = this.t; 706 | } 707 | else { 708 | f = this.s&this.DM; 709 | for(i = m; i < a.t; ++i) r[i] = op(f,a[i]); 710 | r.t = a.t; 711 | } 712 | r.s = op(this.s,a.s); 713 | r.clamp(); 714 | } 715 | 716 | // (public) this & a 717 | function op_and(x,y) { return x&y; } 718 | function bnAnd(a) { var r = nbi(); this.bitwiseTo(a,op_and,r); return r; } 719 | 720 | // (public) this | a 721 | function op_or(x,y) { return x|y; } 722 | function bnOr(a) { var r = nbi(); this.bitwiseTo(a,op_or,r); return r; } 723 | 724 | // (public) this ^ a 725 | function op_xor(x,y) { return x^y; } 726 | function bnXor(a) { var r = nbi(); this.bitwiseTo(a,op_xor,r); return r; } 727 | 728 | // (public) this & ~a 729 | function op_andnot(x,y) { return x&~y; } 730 | function bnAndNot(a) { var r = nbi(); this.bitwiseTo(a,op_andnot,r); return r; } 731 | 732 | // (public) ~this 733 | function bnNot() { 734 | var r = nbi(); 735 | for(var i = 0; i < this.t; ++i) r[i] = this.DM&~this[i]; 736 | r.t = this.t; 737 | r.s = ~this.s; 738 | return r; 739 | } 740 | 741 | // (public) this << n 742 | function bnShiftLeft(n) { 743 | var r = nbi(); 744 | if(n < 0) this.rShiftTo(-n,r); else this.lShiftTo(n,r); 745 | return r; 746 | } 747 | 748 | // (public) this >> n 749 | function bnShiftRight(n) { 750 | var r = nbi(); 751 | if(n < 0) this.lShiftTo(-n,r); else this.rShiftTo(n,r); 752 | return r; 753 | } 754 | 755 | // return index of lowest 1-bit in x, x < 2^31 756 | function lbit(x) { 757 | if(x == 0) return -1; 758 | var r = 0; 759 | if((x&0xffff) == 0) { x >>= 16; r += 16; } 760 | if((x&0xff) == 0) { x >>= 8; r += 8; } 761 | if((x&0xf) == 0) { x >>= 4; r += 4; } 762 | if((x&3) == 0) { x >>= 2; r += 2; } 763 | if((x&1) == 0) ++r; 764 | return r; 765 | } 766 | 767 | // (public) returns index of lowest 1-bit (or -1 if none) 768 | function bnGetLowestSetBit() { 769 | for(var i = 0; i < this.t; ++i) 770 | if(this[i] != 0) return i*this.DB+lbit(this[i]); 771 | if(this.s < 0) return this.t*this.DB; 772 | return -1; 773 | } 774 | 775 | // return number of 1 bits in x 776 | function cbit(x) { 777 | var r = 0; 778 | while(x != 0) { x &= x-1; ++r; } 779 | return r; 780 | } 781 | 782 | // (public) return number of set bits 783 | function bnBitCount() { 784 | var r = 0, x = this.s&this.DM; 785 | for(var i = 0; i < this.t; ++i) r += cbit(this[i]^x); 786 | return r; 787 | } 788 | 789 | // (public) true iff nth bit is set 790 | function bnTestBit(n) { 791 | var j = Math.floor(n/this.DB); 792 | if(j >= this.t) return(this.s!=0); 793 | return((this[j]&(1<<(n%this.DB)))!=0); 794 | } 795 | 796 | // (protected) this op (1<>= this.DB; 819 | } 820 | if(a.t < this.t) { 821 | c += a.s; 822 | while(i < this.t) { 823 | c += this[i]; 824 | r[i++] = c&this.DM; 825 | c >>= this.DB; 826 | } 827 | c += this.s; 828 | } 829 | else { 830 | c += this.s; 831 | while(i < a.t) { 832 | c += a[i]; 833 | r[i++] = c&this.DM; 834 | c >>= this.DB; 835 | } 836 | c += a.s; 837 | } 838 | r.s = (c<0)?-1:0; 839 | if(c > 0) r[i++] = c; 840 | else if(c < -1) r[i++] = this.DV+c; 841 | r.t = i; 842 | r.clamp(); 843 | } 844 | 845 | // (public) this + a 846 | function bnAdd(a) { var r = nbi(); this.addTo(a,r); return r; } 847 | 848 | // (public) this - a 849 | function bnSubtract(a) { var r = nbi(); this.subTo(a,r); return r; } 850 | 851 | // (public) this * a 852 | function bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; } 853 | 854 | // (public) this^2 855 | function bnSquare() { var r = nbi(); this.squareTo(r); return r; } 856 | 857 | // (public) this / a 858 | function bnDivide(a) { var r = nbi(); this.divRemTo(a,r,null); return r; } 859 | 860 | // (public) this % a 861 | function bnRemainder(a) { var r = nbi(); this.divRemTo(a,null,r); return r; } 862 | 863 | // (public) [this/a,this%a] 864 | function bnDivideAndRemainder(a) { 865 | var q = nbi(), r = nbi(); 866 | this.divRemTo(a,q,r); 867 | return new Array(q,r); 868 | } 869 | 870 | // (protected) this *= n, this >= 0, 1 < n < DV 871 | function bnpDMultiply(n) { 872 | this[this.t] = this.am(0,n-1,this,0,0,this.t); 873 | ++this.t; 874 | this.clamp(); 875 | } 876 | 877 | // (protected) this += n << w words, this >= 0 878 | function bnpDAddOffset(n,w) { 879 | if(n == 0) return; 880 | while(this.t <= w) this[this.t++] = 0; 881 | this[w] += n; 882 | while(this[w] >= this.DV) { 883 | this[w] -= this.DV; 884 | if(++w >= this.t) this[this.t++] = 0; 885 | ++this[w]; 886 | } 887 | } 888 | 889 | // A "null" reducer 890 | function NullExp() {} 891 | function nNop(x) { return x; } 892 | function nMulTo(x,y,r) { x.multiplyTo(y,r); } 893 | function nSqrTo(x,r) { x.squareTo(r); } 894 | 895 | NullExp.prototype.convert = nNop; 896 | NullExp.prototype.revert = nNop; 897 | NullExp.prototype.mulTo = nMulTo; 898 | NullExp.prototype.sqrTo = nSqrTo; 899 | 900 | // (public) this^e 901 | function bnPow(e) { return this.exp(e,new NullExp()); } 902 | 903 | // (protected) r = lower n words of "this * a", a.t <= n 904 | // "this" should be the larger one if appropriate. 905 | function bnpMultiplyLowerTo(a,n,r) { 906 | var i = Math.min(this.t+a.t,n); 907 | r.s = 0; // assumes a,this >= 0 908 | r.t = i; 909 | while(i > 0) r[--i] = 0; 910 | var j; 911 | for(j = r.t-this.t; i < j; ++i) r[i+this.t] = this.am(0,a[i],r,i,0,this.t); 912 | for(j = Math.min(a.t,n); i < j; ++i) this.am(0,a[i],r,i,0,n-i); 913 | r.clamp(); 914 | } 915 | 916 | // (protected) r = "this * a" without lower n words, n > 0 917 | // "this" should be the larger one if appropriate. 918 | function bnpMultiplyUpperTo(a,n,r) { 919 | --n; 920 | var i = r.t = this.t+a.t-n; 921 | r.s = 0; // assumes a,this >= 0 922 | while(--i >= 0) r[i] = 0; 923 | for(i = Math.max(n-this.t,0); i < a.t; ++i) 924 | r[this.t+i-n] = this.am(n-i,a[i],r,0,0,this.t+i-n); 925 | r.clamp(); 926 | r.drShiftTo(1,r); 927 | } 928 | 929 | // Barrett modular reduction 930 | function Barrett(m) { 931 | // setup Barrett 932 | this.r2 = nbi(); 933 | this.q3 = nbi(); 934 | BigInteger.ONE.dlShiftTo(2*m.t,this.r2); 935 | this.mu = this.r2.divide(m); 936 | this.m = m; 937 | } 938 | 939 | function barrettConvert(x) { 940 | if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m); 941 | else if(x.compareTo(this.m) < 0) return x; 942 | else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; } 943 | } 944 | 945 | function barrettRevert(x) { return x; } 946 | 947 | // x = x mod m (HAC 14.42) 948 | function barrettReduce(x) { 949 | x.drShiftTo(this.m.t-1,this.r2); 950 | if(x.t > this.m.t+1) { x.t = this.m.t+1; x.clamp(); } 951 | this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3); 952 | this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2); 953 | while(x.compareTo(this.r2) < 0) x.dAddOffset(1,this.m.t+1); 954 | x.subTo(this.r2,x); 955 | while(x.compareTo(this.m) >= 0) x.subTo(this.m,x); 956 | } 957 | 958 | // r = x^2 mod m; x != r 959 | function barrettSqrTo(x,r) { x.squareTo(r); this.reduce(r); } 960 | 961 | // r = x*y mod m; x,y != r 962 | function barrettMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } 963 | 964 | Barrett.prototype.convert = barrettConvert; 965 | Barrett.prototype.revert = barrettRevert; 966 | Barrett.prototype.reduce = barrettReduce; 967 | Barrett.prototype.mulTo = barrettMulTo; 968 | Barrett.prototype.sqrTo = barrettSqrTo; 969 | 970 | // (public) this^e % m (HAC 14.85) 971 | function bnModPow(e,m) { 972 | var i = e.bitLength(), k, r = nbv(1), z; 973 | if(i <= 0) return r; 974 | else if(i < 18) k = 1; 975 | else if(i < 48) k = 3; 976 | else if(i < 144) k = 4; 977 | else if(i < 768) k = 5; 978 | else k = 6; 979 | if(i < 8) 980 | z = new Classic(m); 981 | else if(m.isEven()) 982 | z = new Barrett(m); 983 | else 984 | z = new Montgomery(m); 985 | 986 | // precomputation 987 | var g = new Array(), n = 3, k1 = k-1, km = (1< 1) { 990 | var g2 = nbi(); 991 | z.sqrTo(g[1],g2); 992 | while(n <= km) { 993 | g[n] = nbi(); 994 | z.mulTo(g2,g[n-2],g[n]); 995 | n += 2; 996 | } 997 | } 998 | 999 | var j = e.t-1, w, is1 = true, r2 = nbi(), t; 1000 | i = nbits(e[j])-1; 1001 | while(j >= 0) { 1002 | if(i >= k1) w = (e[j]>>(i-k1))&km; 1003 | else { 1004 | w = (e[j]&((1<<(i+1))-1))<<(k1-i); 1005 | if(j > 0) w |= e[j-1]>>(this.DB+i-k1); 1006 | } 1007 | 1008 | n = k; 1009 | while((w&1) == 0) { w >>= 1; --n; } 1010 | if((i -= n) < 0) { i += this.DB; --j; } 1011 | if(is1) { // ret == 1, don't bother squaring or multiplying it 1012 | g[w].copyTo(r); 1013 | is1 = false; 1014 | } 1015 | else { 1016 | while(n > 1) { z.sqrTo(r,r2); z.sqrTo(r2,r); n -= 2; } 1017 | if(n > 0) z.sqrTo(r,r2); else { t = r; r = r2; r2 = t; } 1018 | z.mulTo(r2,g[w],r); 1019 | } 1020 | 1021 | while(j >= 0 && (e[j]&(1< 0) { 1038 | x.rShiftTo(g,x); 1039 | y.rShiftTo(g,y); 1040 | } 1041 | while(x.signum() > 0) { 1042 | if((i = x.getLowestSetBit()) > 0) x.rShiftTo(i,x); 1043 | if((i = y.getLowestSetBit()) > 0) y.rShiftTo(i,y); 1044 | if(x.compareTo(y) >= 0) { 1045 | x.subTo(y,x); 1046 | x.rShiftTo(1,x); 1047 | } 1048 | else { 1049 | y.subTo(x,y); 1050 | y.rShiftTo(1,y); 1051 | } 1052 | } 1053 | if(g > 0) y.lShiftTo(g,y); 1054 | return y; 1055 | } 1056 | 1057 | // (protected) this % n, n < 2^26 1058 | function bnpModInt(n) { 1059 | if(n <= 0) return 0; 1060 | var d = this.DV%n, r = (this.s<0)?n-1:0; 1061 | if(this.t > 0) 1062 | if(d == 0) r = this[0]%n; 1063 | else for(var i = this.t-1; i >= 0; --i) r = (d*r+this[i])%n; 1064 | return r; 1065 | } 1066 | 1067 | // (public) 1/this % m (HAC 14.61) 1068 | function bnModInverse(m) { 1069 | var ac = m.isEven(); 1070 | if((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO; 1071 | var u = m.clone(), v = this.clone(); 1072 | var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1); 1073 | while(u.signum() != 0) { 1074 | while(u.isEven()) { 1075 | u.rShiftTo(1,u); 1076 | if(ac) { 1077 | if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); } 1078 | a.rShiftTo(1,a); 1079 | } 1080 | else if(!b.isEven()) b.subTo(m,b); 1081 | b.rShiftTo(1,b); 1082 | } 1083 | while(v.isEven()) { 1084 | v.rShiftTo(1,v); 1085 | if(ac) { 1086 | if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); } 1087 | c.rShiftTo(1,c); 1088 | } 1089 | else if(!d.isEven()) d.subTo(m,d); 1090 | d.rShiftTo(1,d); 1091 | } 1092 | if(u.compareTo(v) >= 0) { 1093 | u.subTo(v,u); 1094 | if(ac) a.subTo(c,a); 1095 | b.subTo(d,b); 1096 | } 1097 | else { 1098 | v.subTo(u,v); 1099 | if(ac) c.subTo(a,c); 1100 | d.subTo(b,d); 1101 | } 1102 | } 1103 | if(v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO; 1104 | if(d.compareTo(m) >= 0) return d.subtract(m); 1105 | if(d.signum() < 0) d.addTo(m,d); else return d; 1106 | if(d.signum() < 0) return d.add(m); else return d; 1107 | } 1108 | 1109 | var lowprimes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997]; 1110 | var lplim = (1<<26)/lowprimes[lowprimes.length-1]; 1111 | 1112 | // (public) test primality with certainty >= 1-.5^t 1113 | function bnIsProbablePrime(t) { 1114 | var i, x = this.abs(); 1115 | if(x.t == 1 && x[0] <= lowprimes[lowprimes.length-1]) { 1116 | for(i = 0; i < lowprimes.length; ++i) 1117 | if(x[0] == lowprimes[i]) return true; 1118 | return false; 1119 | } 1120 | if(x.isEven()) return false; 1121 | i = 1; 1122 | while(i < lowprimes.length) { 1123 | var m = lowprimes[i], j = i+1; 1124 | while(j < lowprimes.length && m < lplim) m *= lowprimes[j++]; 1125 | m = x.modInt(m); 1126 | while(i < j) if(m%lowprimes[i++] == 0) return false; 1127 | } 1128 | return x.millerRabin(t); 1129 | } 1130 | 1131 | // (protected) true if probably prime (HAC 4.24, Miller-Rabin) 1132 | function bnpMillerRabin(t) { 1133 | var n1 = this.subtract(BigInteger.ONE); 1134 | var k = n1.getLowestSetBit(); 1135 | if(k <= 0) return false; 1136 | var r = n1.shiftRight(k); 1137 | t = (t+1)>>1; 1138 | if(t > lowprimes.length) t = lowprimes.length; 1139 | var a = nbi(); 1140 | for(var i = 0; i < t; ++i) { 1141 | //Pick bases at random, instead of starting at 2 1142 | a.fromInt(lowprimes[Math.floor(Math.random()*lowprimes.length)]); 1143 | var y = a.modPow(r,this); 1144 | if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) { 1145 | var j = 1; 1146 | while(j++ < k && y.compareTo(n1) != 0) { 1147 | y = y.modPowInt(2,this); 1148 | if(y.compareTo(BigInteger.ONE) == 0) return false; 1149 | } 1150 | if(y.compareTo(n1) != 0) return false; 1151 | } 1152 | } 1153 | return true; 1154 | } 1155 | 1156 | // protected 1157 | BigInteger.prototype.chunkSize = bnpChunkSize; 1158 | BigInteger.prototype.toRadix = bnpToRadix; 1159 | BigInteger.prototype.fromRadix = bnpFromRadix; 1160 | BigInteger.prototype.fromNumber = bnpFromNumber; 1161 | BigInteger.prototype.bitwiseTo = bnpBitwiseTo; 1162 | BigInteger.prototype.changeBit = bnpChangeBit; 1163 | BigInteger.prototype.addTo = bnpAddTo; 1164 | BigInteger.prototype.dMultiply = bnpDMultiply; 1165 | BigInteger.prototype.dAddOffset = bnpDAddOffset; 1166 | BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo; 1167 | BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo; 1168 | BigInteger.prototype.modInt = bnpModInt; 1169 | BigInteger.prototype.millerRabin = bnpMillerRabin; 1170 | 1171 | // public 1172 | BigInteger.prototype.clone = bnClone; 1173 | BigInteger.prototype.intValue = bnIntValue; 1174 | BigInteger.prototype.byteValue = bnByteValue; 1175 | BigInteger.prototype.shortValue = bnShortValue; 1176 | BigInteger.prototype.signum = bnSigNum; 1177 | BigInteger.prototype.toByteArray = bnToByteArray; 1178 | BigInteger.prototype.equals = bnEquals; 1179 | BigInteger.prototype.min = bnMin; 1180 | BigInteger.prototype.max = bnMax; 1181 | BigInteger.prototype.and = bnAnd; 1182 | BigInteger.prototype.or = bnOr; 1183 | BigInteger.prototype.xor = bnXor; 1184 | BigInteger.prototype.andNot = bnAndNot; 1185 | BigInteger.prototype.not = bnNot; 1186 | BigInteger.prototype.shiftLeft = bnShiftLeft; 1187 | BigInteger.prototype.shiftRight = bnShiftRight; 1188 | BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit; 1189 | BigInteger.prototype.bitCount = bnBitCount; 1190 | BigInteger.prototype.testBit = bnTestBit; 1191 | BigInteger.prototype.setBit = bnSetBit; 1192 | BigInteger.prototype.clearBit = bnClearBit; 1193 | BigInteger.prototype.flipBit = bnFlipBit; 1194 | BigInteger.prototype.add = bnAdd; 1195 | BigInteger.prototype.subtract = bnSubtract; 1196 | BigInteger.prototype.multiply = bnMultiply; 1197 | BigInteger.prototype.divide = bnDivide; 1198 | BigInteger.prototype.remainder = bnRemainder; 1199 | BigInteger.prototype.divideAndRemainder = bnDivideAndRemainder; 1200 | BigInteger.prototype.modPow = bnModPow; 1201 | BigInteger.prototype.modInverse = bnModInverse; 1202 | BigInteger.prototype.pow = bnPow; 1203 | BigInteger.prototype.gcd = bnGCD; 1204 | BigInteger.prototype.isProbablePrime = bnIsProbablePrime; 1205 | 1206 | // JSBN-specific extension 1207 | BigInteger.prototype.square = bnSquare; 1208 | 1209 | // BigInteger interfaces not implemented in jsbn: 1210 | 1211 | // BigInteger(int signum, byte[] magnitude) 1212 | // double doubleValue() 1213 | // float floatValue() 1214 | // int hashCode() 1215 | // long longValue() 1216 | // static BigInteger valueOf(long val) 1217 | 1218 | module.exports = BigInteger; -------------------------------------------------------------------------------- /lib/server.js: -------------------------------------------------------------------------------- 1 | /** 2 | * User: Kurten 3 | * Date: 14-3-1 4 | * Time: 14:38 5 | * Version: 1.0 6 | * Description: 7 | */ 8 | var http = require('http'); 9 | var url = require('url'); 10 | var snowflake = require('./snowflake'); 11 | 12 | module.exports = function(port) { 13 | http.createServer(function (req, res) { 14 | var uobj = url.parse(req.url, true); 15 | if (uobj.pathname == '/next_id') { 16 | res.writeHead(200, {'Content-Type': 'application/json'}); 17 | var query = uobj.query || {}; 18 | var id = snowflake.nextId(query.worker_id, query.data_center_id, query.sequence); 19 | res.end(JSON.stringify({id : id})); 20 | } else { 21 | res.writeHead(404, {'Content-Type': 'application/json'}); 22 | res.end(JSON.stringify({status : 404, msg : 'request url error, not found url'})); 23 | } 24 | }).listen(port || 3000); 25 | 26 | console.log('now server listen port ' + (port || 3000)); 27 | 28 | process.on("uncaughtException", function (err) { 29 | console.trace("uncaughtException:" + err.stack); 30 | }); 31 | }; -------------------------------------------------------------------------------- /lib/snowflake.js: -------------------------------------------------------------------------------- 1 | /** 2 | * User: Kurten 3 | * Date: 14-3-1 4 | * Time: 11:24 5 | * Version: 1.0 6 | * Description: 7 | */ 8 | var snowflake = module.exports; 9 | 10 | var twepoch = 1288834974657; 11 | var workerIdBits = 5; 12 | var dataCenterIdBits = 5; 13 | var maxWrokerId = -1 ^ (-1 << workerIdBits); 14 | var maxDataCenterId = -1 ^ (-1 << dataCenterIdBits); 15 | var sequenceBits = 12; 16 | var workerIdShift = sequenceBits; 17 | var dataCenterIdShift = sequenceBits + workerIdBits; 18 | var timestampLeftShift = sequenceBits + workerIdBits + dataCenterIdBits; 19 | var sequenceMask = -1 ^ (-1 << sequenceBits); 20 | var lastTimestamp = -1; 21 | var BigInteger = require("./jsbn"); 22 | //设置默认值,从环境变量取 23 | var c_workerId = 1; 24 | var c_dataCenterId = 1; 25 | var c_sequence = 0; 26 | 27 | snowflake.init = function (config) { 28 | if (!isNaN(config.worker_id)) { 29 | c_workerId = Number(config.worker_id); 30 | } 31 | if (!isNaN(config.data_center_id)) { 32 | c_dataCenterId = Number(config.data_center_id); 33 | } 34 | if (!isNaN(config.sequence)) { 35 | c_sequence = Number(config.sequence); 36 | } 37 | if (c_workerId > maxWrokerId || c_workerId < 0) { 38 | throw new Error('config.worker_id must max than 0 and small than maxWrokerId-[' + 39 | maxWrokerId + ']'); 40 | } 41 | if (c_dataCenterId > maxDataCenterId || c_dataCenterId < 0) { 42 | throw new Error('config.data_center_id must max than 0 and small than maxDataCenterId-[' + 43 | maxDataCenterId + ']'); 44 | } 45 | }; 46 | 47 | snowflake.nextId = function (workerId, dataCenterId, sequence) { 48 | if (!isNaN(workerId)) { 49 | workerId = Number(workerId); 50 | } else { 51 | workerId = c_workerId; 52 | } 53 | if (!isNaN(dataCenterId)) { 54 | dataCenterId = Number(dataCenterId); 55 | } else { 56 | dataCenterId = c_dataCenterId; 57 | } 58 | if (!isNaN(sequence)) { 59 | sequence = Number(sequence); 60 | } else { 61 | sequence = c_sequence; 62 | } 63 | 64 | if (workerId > maxWrokerId || workerId < 0) { 65 | throw new Error('workerId must max than 0 and small than maxWrokerId-[' + 66 | maxWrokerId + ']'); 67 | } 68 | if (dataCenterId > maxDataCenterId || dataCenterId < 0) { 69 | throw new Error('dataCenterId must max than 0 and small than maxDataCenterId-[' + 70 | maxDataCenterId + ']'); 71 | } 72 | 73 | var timestamp = timeGen(); 74 | if (lastTimestamp === timestamp) { 75 | sequence = (sequence + 1) & sequenceMask; 76 | if (sequence === 0) { 77 | timestamp = tilNextMillis(lastTimestamp); 78 | } 79 | } else { 80 | sequence = 0; 81 | } 82 | if (timestamp < lastTimestamp) { 83 | throw new Error('Clock moved backwards. Refusing to generate id for ' + 84 | (lastTimestamp - timestamp)); 85 | } 86 | 87 | lastTimestamp = timestamp; 88 | var shiftNum = (dataCenterId << dataCenterIdShift) | 89 | (workerId << workerIdShift) | sequence; 90 | var nfirst = new BigInteger(String(timestamp - twepoch), 10); 91 | nfirst = nfirst.shiftLeft(timestampLeftShift); 92 | var nnextId = nfirst.or(new BigInteger(String(shiftNum), 10)); 93 | var nextId = nnextId.toRadix(10); 94 | return String(nextId); 95 | }; 96 | 97 | function tilNextMillis(lastTimestamp) { 98 | var timestamp = timeGen(); 99 | while (timestamp <= lastTimestamp) { 100 | timestamp = timeGen(); 101 | } 102 | return timestamp; 103 | } 104 | 105 | function timeGen() { 106 | var dt = new Date(); 107 | return dt.getTime(); 108 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-snowflake", 3 | "version": "0.0.1", 4 | "description": "a node.js clone for twitter snowflake", 5 | "main": "index.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "http://github.com/kurten/node-snowflake.git" 9 | }, 10 | "keywords": [ 11 | "node.js", 12 | "javascript", 13 | "snowflake", 14 | "twitter" 15 | ], 16 | "author": "Kurten Chan", 17 | "license": "MIT", 18 | "bugs": { 19 | "url": "https://github.com/kurten/node-snowflake/issues" 20 | } 21 | } 22 | --------------------------------------------------------------------------------