bitwise.js 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.bitAndBigNumber = bitAndBigNumber;
  6. exports.bitNotBigNumber = bitNotBigNumber;
  7. exports.bitOrBigNumber = bitOrBigNumber;
  8. exports.bitXor = bitXor;
  9. exports.bitwise = bitwise;
  10. exports.leftShiftBigNumber = leftShiftBigNumber;
  11. exports.rightArithShiftBigNumber = rightArithShiftBigNumber;
  12. /**
  13. * Bitwise and for Bignumbers
  14. *
  15. * Special Cases:
  16. * N & n = N
  17. * n & 0 = 0
  18. * n & -1 = n
  19. * n & n = n
  20. * I & I = I
  21. * -I & -I = -I
  22. * I & -I = 0
  23. * I & n = n
  24. * I & -n = I
  25. * -I & n = 0
  26. * -I & -n = -I
  27. *
  28. * @param {BigNumber} x
  29. * @param {BigNumber} y
  30. * @return {BigNumber} Result of `x` & `y`, is fully precise
  31. * @private
  32. */
  33. function bitAndBigNumber(x, y) {
  34. if (x.isFinite() && !x.isInteger() || y.isFinite() && !y.isInteger()) {
  35. throw new Error('Integers expected in function bitAnd');
  36. }
  37. var BigNumber = x.constructor;
  38. if (x.isNaN() || y.isNaN()) {
  39. return new BigNumber(NaN);
  40. }
  41. if (x.isZero() || y.eq(-1) || x.eq(y)) {
  42. return x;
  43. }
  44. if (y.isZero() || x.eq(-1)) {
  45. return y;
  46. }
  47. if (!x.isFinite() || !y.isFinite()) {
  48. if (!x.isFinite() && !y.isFinite()) {
  49. if (x.isNegative() === y.isNegative()) {
  50. return x;
  51. }
  52. return new BigNumber(0);
  53. }
  54. if (!x.isFinite()) {
  55. if (y.isNegative()) {
  56. return x;
  57. }
  58. if (x.isNegative()) {
  59. return new BigNumber(0);
  60. }
  61. return y;
  62. }
  63. if (!y.isFinite()) {
  64. if (x.isNegative()) {
  65. return y;
  66. }
  67. if (y.isNegative()) {
  68. return new BigNumber(0);
  69. }
  70. return x;
  71. }
  72. }
  73. return bitwise(x, y, function (a, b) {
  74. return a & b;
  75. });
  76. }
  77. /**
  78. * Bitwise not
  79. * @param {BigNumber} x
  80. * @return {BigNumber} Result of ~`x`, fully precise
  81. *
  82. */
  83. function bitNotBigNumber(x) {
  84. if (x.isFinite() && !x.isInteger()) {
  85. throw new Error('Integer expected in function bitNot');
  86. }
  87. var BigNumber = x.constructor;
  88. var prevPrec = BigNumber.precision;
  89. BigNumber.config({
  90. precision: 1E9
  91. });
  92. var result = x.plus(new BigNumber(1));
  93. result.s = -result.s || null;
  94. BigNumber.config({
  95. precision: prevPrec
  96. });
  97. return result;
  98. }
  99. /**
  100. * Bitwise OR for BigNumbers
  101. *
  102. * Special Cases:
  103. * N | n = N
  104. * n | 0 = n
  105. * n | -1 = -1
  106. * n | n = n
  107. * I | I = I
  108. * -I | -I = -I
  109. * I | -n = -1
  110. * I | -I = -1
  111. * I | n = I
  112. * -I | n = -I
  113. * -I | -n = -n
  114. *
  115. * @param {BigNumber} x
  116. * @param {BigNumber} y
  117. * @return {BigNumber} Result of `x` | `y`, fully precise
  118. */
  119. function bitOrBigNumber(x, y) {
  120. if (x.isFinite() && !x.isInteger() || y.isFinite() && !y.isInteger()) {
  121. throw new Error('Integers expected in function bitOr');
  122. }
  123. var BigNumber = x.constructor;
  124. if (x.isNaN() || y.isNaN()) {
  125. return new BigNumber(NaN);
  126. }
  127. var negOne = new BigNumber(-1);
  128. if (x.isZero() || y.eq(negOne) || x.eq(y)) {
  129. return y;
  130. }
  131. if (y.isZero() || x.eq(negOne)) {
  132. return x;
  133. }
  134. if (!x.isFinite() || !y.isFinite()) {
  135. if (!x.isFinite() && !x.isNegative() && y.isNegative() || x.isNegative() && !y.isNegative() && !y.isFinite()) {
  136. return negOne;
  137. }
  138. if (x.isNegative() && y.isNegative()) {
  139. return x.isFinite() ? x : y;
  140. }
  141. return x.isFinite() ? y : x;
  142. }
  143. return bitwise(x, y, function (a, b) {
  144. return a | b;
  145. });
  146. }
  147. /**
  148. * Applies bitwise function to numbers
  149. * @param {BigNumber} x
  150. * @param {BigNumber} y
  151. * @param {function (a, b)} func
  152. * @return {BigNumber}
  153. */
  154. function bitwise(x, y, func) {
  155. var BigNumber = x.constructor;
  156. var xBits, yBits;
  157. var xSign = +(x.s < 0);
  158. var ySign = +(y.s < 0);
  159. if (xSign) {
  160. xBits = decCoefficientToBinaryString(bitNotBigNumber(x));
  161. for (var i = 0; i < xBits.length; ++i) {
  162. xBits[i] ^= 1;
  163. }
  164. } else {
  165. xBits = decCoefficientToBinaryString(x);
  166. }
  167. if (ySign) {
  168. yBits = decCoefficientToBinaryString(bitNotBigNumber(y));
  169. for (var _i = 0; _i < yBits.length; ++_i) {
  170. yBits[_i] ^= 1;
  171. }
  172. } else {
  173. yBits = decCoefficientToBinaryString(y);
  174. }
  175. var minBits, maxBits, minSign;
  176. if (xBits.length <= yBits.length) {
  177. minBits = xBits;
  178. maxBits = yBits;
  179. minSign = xSign;
  180. } else {
  181. minBits = yBits;
  182. maxBits = xBits;
  183. minSign = ySign;
  184. }
  185. var shortLen = minBits.length;
  186. var longLen = maxBits.length;
  187. var expFuncVal = func(xSign, ySign) ^ 1;
  188. var outVal = new BigNumber(expFuncVal ^ 1);
  189. var twoPower = new BigNumber(1);
  190. var two = new BigNumber(2);
  191. var prevPrec = BigNumber.precision;
  192. BigNumber.config({
  193. precision: 1E9
  194. });
  195. while (shortLen > 0) {
  196. if (func(minBits[--shortLen], maxBits[--longLen]) === expFuncVal) {
  197. outVal = outVal.plus(twoPower);
  198. }
  199. twoPower = twoPower.times(two);
  200. }
  201. while (longLen > 0) {
  202. if (func(minSign, maxBits[--longLen]) === expFuncVal) {
  203. outVal = outVal.plus(twoPower);
  204. }
  205. twoPower = twoPower.times(two);
  206. }
  207. BigNumber.config({
  208. precision: prevPrec
  209. });
  210. if (expFuncVal === 0) {
  211. outVal.s = -outVal.s;
  212. }
  213. return outVal;
  214. }
  215. /* Extracted from decimal.js, and edited to specialize. */
  216. function decCoefficientToBinaryString(x) {
  217. // Convert to string
  218. var a = x.d; // array with digits
  219. var r = a[0] + '';
  220. for (var i = 1; i < a.length; ++i) {
  221. var s = a[i] + '';
  222. for (var z = 7 - s.length; z--;) {
  223. s = '0' + s;
  224. }
  225. r += s;
  226. }
  227. var j = r.length;
  228. while (r.charAt(j) === '0') {
  229. j--;
  230. }
  231. var xe = x.e;
  232. var str = r.slice(0, j + 1 || 1);
  233. var strL = str.length;
  234. if (xe > 0) {
  235. if (++xe > strL) {
  236. // Append zeros.
  237. xe -= strL;
  238. while (xe--) {
  239. str += '0';
  240. }
  241. } else if (xe < strL) {
  242. str = str.slice(0, xe) + '.' + str.slice(xe);
  243. }
  244. }
  245. // Convert from base 10 (decimal) to base 2
  246. var arr = [0];
  247. for (var _i2 = 0; _i2 < str.length;) {
  248. var arrL = arr.length;
  249. while (arrL--) {
  250. arr[arrL] *= 10;
  251. }
  252. arr[0] += parseInt(str.charAt(_i2++)); // convert to int
  253. for (var _j = 0; _j < arr.length; ++_j) {
  254. if (arr[_j] > 1) {
  255. if (arr[_j + 1] === null || arr[_j + 1] === undefined) {
  256. arr[_j + 1] = 0;
  257. }
  258. arr[_j + 1] += arr[_j] >> 1;
  259. arr[_j] &= 1;
  260. }
  261. }
  262. }
  263. return arr.reverse();
  264. }
  265. /**
  266. * Bitwise XOR for BigNumbers
  267. *
  268. * Special Cases:
  269. * N ^ n = N
  270. * n ^ 0 = n
  271. * n ^ n = 0
  272. * n ^ -1 = ~n
  273. * I ^ n = I
  274. * I ^ -n = -I
  275. * I ^ -I = -1
  276. * -I ^ n = -I
  277. * -I ^ -n = I
  278. *
  279. * @param {BigNumber} x
  280. * @param {BigNumber} y
  281. * @return {BigNumber} Result of `x` ^ `y`, fully precise
  282. *
  283. */
  284. function bitXor(x, y) {
  285. if (x.isFinite() && !x.isInteger() || y.isFinite() && !y.isInteger()) {
  286. throw new Error('Integers expected in function bitXor');
  287. }
  288. var BigNumber = x.constructor;
  289. if (x.isNaN() || y.isNaN()) {
  290. return new BigNumber(NaN);
  291. }
  292. if (x.isZero()) {
  293. return y;
  294. }
  295. if (y.isZero()) {
  296. return x;
  297. }
  298. if (x.eq(y)) {
  299. return new BigNumber(0);
  300. }
  301. var negOne = new BigNumber(-1);
  302. if (x.eq(negOne)) {
  303. return bitNotBigNumber(y);
  304. }
  305. if (y.eq(negOne)) {
  306. return bitNotBigNumber(x);
  307. }
  308. if (!x.isFinite() || !y.isFinite()) {
  309. if (!x.isFinite() && !y.isFinite()) {
  310. return negOne;
  311. }
  312. return new BigNumber(x.isNegative() === y.isNegative() ? Infinity : -Infinity);
  313. }
  314. return bitwise(x, y, function (a, b) {
  315. return a ^ b;
  316. });
  317. }
  318. /**
  319. * Bitwise left shift
  320. *
  321. * Special Cases:
  322. * n << -n = N
  323. * n << N = N
  324. * N << n = N
  325. * n << 0 = n
  326. * 0 << n = 0
  327. * I << I = N
  328. * I << n = I
  329. * n << I = I
  330. *
  331. * @param {BigNumber} x
  332. * @param {BigNumber} y
  333. * @return {BigNumber} Result of `x` << `y`
  334. *
  335. */
  336. function leftShiftBigNumber(x, y) {
  337. if (x.isFinite() && !x.isInteger() || y.isFinite() && !y.isInteger()) {
  338. throw new Error('Integers expected in function leftShift');
  339. }
  340. var BigNumber = x.constructor;
  341. if (x.isNaN() || y.isNaN() || y.isNegative() && !y.isZero()) {
  342. return new BigNumber(NaN);
  343. }
  344. if (x.isZero() || y.isZero()) {
  345. return x;
  346. }
  347. if (!x.isFinite() && !y.isFinite()) {
  348. return new BigNumber(NaN);
  349. }
  350. // Math.pow(2, y) is fully precise for y < 55, and fast
  351. if (y.lt(55)) {
  352. return x.times(Math.pow(2, y.toNumber()) + '');
  353. }
  354. return x.times(new BigNumber(2).pow(y));
  355. }
  356. /*
  357. * Special Cases:
  358. * n >> -n = N
  359. * n >> N = N
  360. * N >> n = N
  361. * I >> I = N
  362. * n >> 0 = n
  363. * I >> n = I
  364. * -I >> n = -I
  365. * -I >> I = -I
  366. * n >> I = I
  367. * -n >> I = -1
  368. * 0 >> n = 0
  369. *
  370. * @param {BigNumber} value
  371. * @param {BigNumber} value
  372. * @return {BigNumber} Result of `x` >> `y`
  373. *
  374. */
  375. function rightArithShiftBigNumber(x, y) {
  376. if (x.isFinite() && !x.isInteger() || y.isFinite() && !y.isInteger()) {
  377. throw new Error('Integers expected in function rightArithShift');
  378. }
  379. var BigNumber = x.constructor;
  380. if (x.isNaN() || y.isNaN() || y.isNegative() && !y.isZero()) {
  381. return new BigNumber(NaN);
  382. }
  383. if (x.isZero() || y.isZero()) {
  384. return x;
  385. }
  386. if (!y.isFinite()) {
  387. if (x.isNegative()) {
  388. return new BigNumber(-1);
  389. }
  390. if (!x.isFinite()) {
  391. return new BigNumber(NaN);
  392. }
  393. return new BigNumber(0);
  394. }
  395. // Math.pow(2, y) is fully precise for y < 55, and fast
  396. if (y.lt(55)) {
  397. return x.div(Math.pow(2, y.toNumber()) + '').floor();
  398. }
  399. return x.div(new BigNumber(2).pow(y)).floor();
  400. }