Created
April 30, 2011 09:13
-
-
Save edvakf/949546 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| var bigint; | |
| // very very basic bigint class. | |
| // complete version: https://github.com/dankogai/js-math-bigint | |
| (function() { | |
| // Original: http://www.onicos.com/staff/iz/amuse/javascript/expert/BigInt.txt | |
| // | |
| // BigInt.js - Arbitrary size integer math package for JavaScript | |
| // Copyright (C) 2000 Masanao Izumo <iz@onicos.co.jp> | |
| // Copyright (C) 2010 Dan Kogai <dankogai+404bnf@gmail.com> | |
| // Version: 1.0.1 | |
| // Licence: GPL | |
| // | |
| // This program is free software; you can redistribute it and/or modify | |
| // it under the terms of the GNU General Public License as published by | |
| // the Free Software Foundation; either version 2 of the License, or | |
| // (at your option) any later version. | |
| // | |
| // This program is distributed in the hope that it will be useful, | |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| // GNU General Public License for more details. | |
| // | |
| // bigint_sub_internal was buggy so rewritten. | |
| function _BigInt_toString() { | |
| return this.toStringBase(10); | |
| } | |
| function _BigInt_toStringBase(base) { | |
| var i, j, hbase, t, ds, c; | |
| i = this.len; | |
| if (i === 0) return '0'; | |
| if (i === 1 && !this.digits[0]) return '0'; | |
| switch (base) { | |
| default: | |
| case 10: | |
| j = Math.floor((2 * 8 * i * 241) / 800) + 2; | |
| hbase = 10000; | |
| break; | |
| case 16: | |
| j = Math.floor((2 * 8 * i) / 4) + 2; | |
| hbase = 0x10000; | |
| break; | |
| case 8: | |
| j = (2 * 8 * i) + 2; | |
| hbase = 010000; | |
| break; | |
| case 2: | |
| j = (2 * 8 * i) + 2; | |
| hbase = 020; | |
| break; | |
| } | |
| t = this.clone(); | |
| ds = t.digits; | |
| s = ''; | |
| while (i && j) { | |
| var k = i, num = 0; | |
| while (k--) { | |
| num = (num << 16) + ds[k]; | |
| if (num < 0) num += 4294967296; | |
| ds[k] = Math.floor(num / hbase); | |
| num %= hbase; | |
| } | |
| if (ds[i - 1] === 0) i--; | |
| k = 4; | |
| while (k--) { | |
| c = (num % base); | |
| s = '0123456789abcdef'.charAt(c) + s; | |
| --j; | |
| num = Math.floor(num / base); | |
| if (i === 0 && num === 0) { | |
| break; | |
| } | |
| } | |
| } | |
| i = 0; | |
| while (i < s.length && s.charAt(i) === '0') i++; | |
| if (i) s = s.substring(i, s.length); | |
| if (!this.sign) s = '-' + s; | |
| return s; | |
| } | |
| function _BigInt_clone() { | |
| var i, l, x = new BigInt(this.len, this.sign); | |
| for (i = 0, l = this.len; i < l; i++) x.digits[i] = this.digits[i]; | |
| return x; | |
| } | |
| function BigInt(len, sign) { | |
| var i, x, need_init; | |
| // Setup member functions. | |
| // Note: There is G.C. bug of function() in Netscape! | |
| // Don't use anonymous function. | |
| if (arguments.length === 0) { | |
| this.sign = true; | |
| this.len = len = 1; | |
| this.digits = new Array(1); | |
| need_init = true; | |
| } else if (arguments.length === 1) { | |
| x = bigint_from_any(arguments[0]); | |
| if (x === arguments[0]) x = x.clone(); | |
| this.sign = x.sign; | |
| this.len = x.len; | |
| this.digits = x.digits; | |
| need_init = false; | |
| } else { | |
| this.sign = (sign ? true : false); | |
| this.len = len; | |
| this.digits = new Array(len); | |
| need_init = true; | |
| } | |
| if (need_init) { | |
| for (i = 0; i < len; i++) | |
| this.digits[i] = 0; | |
| } | |
| } | |
| function bigint_norm(x) { | |
| var len = x.len, ds = x.digits; | |
| while (len-- && !ds[len]); | |
| x.len = ++len; | |
| return x; | |
| } | |
| function bigint_from_int(n) { | |
| var sign, big, i; | |
| if (n < 0) { | |
| n = -n; | |
| sign = false; | |
| } else { | |
| sign = true; | |
| } | |
| n &= 0x7fffffff; | |
| if (n <= 0xffff) { | |
| big = new BigInt(1, 1); | |
| big.digits[0] = n; | |
| } else { | |
| big = new BigInt(2, 1); | |
| big.digits[0] = (n & 0xffff); | |
| big.digits[1] = ((n >> 16) & 0xffff); | |
| } | |
| return big; | |
| } | |
| var bzero = bigint_from_int(0); | |
| function bigint_from_string(str, base) { | |
| var str_i, sign = true, c, len, z, zds, num, i, blen = 1; | |
| str += '@'; // Terminator; | |
| str_i = 0; | |
| // TODO: skip white spaces | |
| if (str.charAt(str_i) === '+') { | |
| str_i++; | |
| } else if (str.charAt(str_i) === '-') { | |
| str_i++; | |
| sign = false; | |
| } | |
| if (str.charAt(str_i) === '@') return null; | |
| if (!base) { | |
| if (str.charAt(str_i) === '0') { | |
| c = str.charAt(str_i + 1); | |
| if (c === 'x' || c === 'X') { | |
| base = 16; | |
| } | |
| else if (c === 'b' || c === 'B') { | |
| base = 2; | |
| } | |
| else { | |
| base = 8; | |
| } | |
| } | |
| else { | |
| base = 10; | |
| } | |
| } | |
| if (base === 8) { | |
| while (str.charAt(str_i) === '0') str_i++; | |
| len = 3 * (str.length - str_i); | |
| } else { // base === 10, 2 or 16 | |
| if (base === 16 && str.charAt(str_i) === '0' && | |
| (str.charAt(str_i + 1) === 'x' || str.charAt(str_i + 1) === 'X')) { | |
| str_i += 2; | |
| } | |
| if (base === 2 && str.charAt(str_i) === '0' && | |
| (str.charAt(str_i + 1) === 'b' || str.charAt(str_i + 1) === 'B')) { | |
| str_i += 2; | |
| } | |
| while (str.charAt(str_i) === '0') | |
| str_i++; | |
| if (str.charAt(str_i) === '@') str_i--; | |
| len = 4 * (str.length - str_i); | |
| } | |
| len = (len >> 4) + 1; | |
| z = new BigInt(len, sign); | |
| zds = z.digits; | |
| while (true) { | |
| c = str.charAt(str_i++); | |
| if (c === '@') break; | |
| switch (c) { | |
| case '0': c = 0; break; | |
| case '1': c = 1; break; | |
| case '2': c = 2; break; | |
| case '3': c = 3; break; | |
| case '4': c = 4; break; | |
| case '5': c = 5; break; | |
| case '6': c = 6; break; | |
| case '7': c = 7; break; | |
| case '8': c = 8; break; | |
| case '9': c = 9; break; | |
| case 'a': case 'A': c = 10; break; | |
| case 'b': case 'B': c = 11; break; | |
| case 'c': case 'C': c = 12; break; | |
| case 'd': case 'D': c = 13; break; | |
| case 'e': case 'E': c = 14; break; | |
| case 'f': case 'F': c = 15; break; | |
| default: | |
| c = base; | |
| break; | |
| } | |
| if (c >= base) break; | |
| i = 0; | |
| num = c; | |
| while (true) { | |
| while (i < blen) { | |
| num += zds[i] * base; | |
| zds[i++] = (num & 0xffff); | |
| num >>>= 16; | |
| } | |
| if (num) { | |
| blen++; | |
| continue; | |
| } | |
| break; | |
| } | |
| } | |
| return bigint_norm(z); | |
| } | |
| function bigint_from_any(x) { | |
| if (typeof(x) === 'object') { | |
| return (x instanceof BigInt) ? x : bzero; | |
| } | |
| if (typeof(x) === 'string') { | |
| return bigint_from_string(x); | |
| } | |
| if (typeof(x) === 'number') { | |
| var i, x1, x2, fpt, np; | |
| if (-2147483647 <= x && x <= 2147483647) { | |
| return bigint_from_int(x); | |
| } | |
| x = x + ''; | |
| i = x.indexOf('e', 0); | |
| if (i === -1) return bigint_from_string(x); | |
| x1 = x.substr(0, i); | |
| x2 = x.substr(i + 2, x.length - (i + 2)); | |
| fpt = x1.indexOf('.', 0); | |
| if (fpt != -1) { | |
| np = x1.length - (fpt + 1); | |
| x1 = x1.substr(0, fpt) + x1.substr(fpt + 1, np); | |
| x2 = parseInt(x2) - np; | |
| } else { | |
| x2 = parseInt(x2); | |
| } | |
| while (x2-- > 0) { | |
| x1 += '0'; | |
| } | |
| return bigint_from_string(x1); | |
| } | |
| return BigInt(1, 1); | |
| } | |
| /* | |
| * By Dan Kogai | |
| */ | |
| BigInt.prototype = { | |
| toString: _BigInt_toString, | |
| toStringBase: _BigInt_toStringBase, | |
| clone: _BigInt_clone, | |
| }; | |
| Math.BigInt = BigInt; | |
| bigint = function(a) { return bigint_from_any(a) }; | |
| })(); | |
| var BASE64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'; | |
| function binaryToBase64(bin) { | |
| var base = []; | |
| for (var i = 0, l = bin.length; i < l; ) { | |
| var n = (bin[i++] << 0) // converts undefined to zero | |
| + (bin[i++] << 1) | |
| + (bin[i++] << 2) | |
| + (bin[i++] << 3) | |
| + (bin[i++] << 4) | |
| + (bin[i++] << 5); | |
| base.push(BASE64.charAt(n)); | |
| } | |
| return base.join(''); | |
| } | |
| function base64ToBinary(b64) { | |
| var bin = []; | |
| for (var i = 0, l = b64.length; i < l; i++) { | |
| var n = BASE64.indexOf(b64.charAt(i)); | |
| bin.push(n % 2, | |
| (n >> 1) % 2, | |
| (n >> 2) % 2, | |
| (n >> 3) % 2, | |
| (n >> 4) % 2, | |
| (n >> 5) % 2); | |
| } | |
| while (bin[bin.length - 1] === 0) { | |
| bin.pop(); | |
| } | |
| return bin; | |
| } | |
| var x = bigint("64098252294864896"); // new id (56 bit) | |
| //var x = bigint("25033162086"); // old id (35 bit) | |
| var x2 = x.toStringBase(2); | |
| print(x2); | |
| if (x2.length === 56 && x2.slice(-8) === '00000000') { | |
| // last 8 bits are usually all zero. in that case, remove them | |
| var ba = binaryToBase64(x2.split('').slice(0, -8).reverse()); | |
| } else { | |
| var ba = binaryToBase64(x2.split('').reverse()); | |
| } | |
| print(ba); | |
| var bi = base64ToBinary(ba).reverse().join(''); | |
| print(bi); | |
| if (bi.length === 48) { | |
| bi += '00000000'; | |
| } | |
| print(bi); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment