arith_test.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 Google Inc. All rights reserved.
  3. // https://developers.google.com/protocol-buffers/
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above
  12. // copyright notice, this list of conditions and the following disclaimer
  13. // in the documentation and/or other materials provided with the
  14. // distribution.
  15. // * Neither the name of Google Inc. nor the names of its
  16. // contributors may be used to endorse or promote products derived from
  17. // this software without specific prior written permission.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. /**
  31. * @fileoverview Test cases for Int64-manipulation functions.
  32. *
  33. * Test suite is written using Jasmine -- see http://jasmine.github.io/
  34. *
  35. * @author cfallin@google.com (Chris Fallin)
  36. */
  37. goog.require('jspb.arith.Int64');
  38. goog.require('jspb.arith.UInt64');
  39. describe('binaryArithTest', function() {
  40. /**
  41. * Tests comparison operations.
  42. */
  43. it('testCompare', function() {
  44. var a = new jspb.arith.UInt64(1234, 5678);
  45. var b = new jspb.arith.UInt64(1234, 5678);
  46. expect(a.cmp(b)).toEqual(0);
  47. expect(b.cmp(a)).toEqual(0);
  48. b.lo -= 1;
  49. expect(a.cmp(b)).toEqual(1);
  50. expect(b.cmp(a)).toEqual(-1);
  51. b.lo += 2;
  52. expect(a.cmp(b)).toEqual(-1);
  53. expect(b.cmp(a)).toEqual(1);
  54. b.lo = a.lo;
  55. b.hi = a.hi - 1;
  56. expect(a.cmp(b)).toEqual(1);
  57. expect(b.cmp(a)).toEqual(-1);
  58. expect(a.zero()).toEqual(false);
  59. expect(a.msb()).toEqual(false);
  60. expect(a.lsb()).toEqual(false);
  61. a.hi = 0;
  62. a.lo = 0;
  63. expect(a.zero()).toEqual(true);
  64. a.hi = 0x80000000;
  65. expect(a.zero()).toEqual(false);
  66. expect(a.msb()).toEqual(true);
  67. a.lo = 0x00000001;
  68. expect(a.lsb()).toEqual(true);
  69. });
  70. /**
  71. * Tests shifts.
  72. */
  73. it('testShifts', function() {
  74. var a = new jspb.arith.UInt64(1, 0);
  75. expect(a.lo).toEqual(1);
  76. expect(a.hi).toEqual(0);
  77. var orig = a;
  78. a = a.leftShift();
  79. expect(orig.lo).toEqual(1); // original unmodified.
  80. expect(orig.hi).toEqual(0);
  81. expect(a.lo).toEqual(2);
  82. expect(a.hi).toEqual(0);
  83. a = a.leftShift();
  84. expect(a.lo).toEqual(4);
  85. expect(a.hi).toEqual(0);
  86. for (var i = 0; i < 29; i++) {
  87. a = a.leftShift();
  88. }
  89. expect(a.lo).toEqual(0x80000000);
  90. expect(a.hi).toEqual(0);
  91. a = a.leftShift();
  92. expect(a.lo).toEqual(0);
  93. expect(a.hi).toEqual(1);
  94. a = a.leftShift();
  95. expect(a.lo).toEqual(0);
  96. expect(a.hi).toEqual(2);
  97. a = a.rightShift();
  98. a = a.rightShift();
  99. expect(a.lo).toEqual(0x80000000);
  100. expect(a.hi).toEqual(0);
  101. a = a.rightShift();
  102. expect(a.lo).toEqual(0x40000000);
  103. expect(a.hi).toEqual(0);
  104. });
  105. /**
  106. * Tests additions.
  107. */
  108. it('testAdd', function() {
  109. var a = new jspb.arith.UInt64(/* lo = */ 0x89abcdef,
  110. /* hi = */ 0x01234567);
  111. var b = new jspb.arith.UInt64(/* lo = */ 0xff52ab91,
  112. /* hi = */ 0x92fa2123);
  113. // Addition with carry.
  114. var c = a.add(b);
  115. expect(a.lo).toEqual(0x89abcdef); // originals unmodified.
  116. expect(a.hi).toEqual(0x01234567);
  117. expect(b.lo).toEqual(0xff52ab91);
  118. expect(b.hi).toEqual(0x92fa2123);
  119. expect(c.lo).toEqual(0x88fe7980);
  120. expect(c.hi).toEqual(0x941d668b);
  121. // Simple addition without carry.
  122. a.lo = 2;
  123. a.hi = 0;
  124. b.lo = 3;
  125. b.hi = 0;
  126. c = a.add(b);
  127. expect(c.lo).toEqual(5);
  128. expect(c.hi).toEqual(0);
  129. });
  130. /**
  131. * Test subtractions.
  132. */
  133. it('testSub', function() {
  134. var kLength = 10;
  135. var hiValues = [0x1682ef32,
  136. 0x583902f7,
  137. 0xb62f5955,
  138. 0x6ea99bbf,
  139. 0x25a39c20,
  140. 0x0700a08b,
  141. 0x00f7304d,
  142. 0x91a5b5af,
  143. 0x89077fd2,
  144. 0xe09e347c];
  145. var loValues = [0xe1538b18,
  146. 0xbeacd556,
  147. 0x74100758,
  148. 0x96e3cb26,
  149. 0x56c37c3f,
  150. 0xe00b3f7d,
  151. 0x859f25d7,
  152. 0xc2ee614a,
  153. 0xe1d21cd7,
  154. 0x30aae6a4];
  155. for (var i = 0; i < kLength; i++) {
  156. for (var j = 0; j < kLength; j++) {
  157. var a = new jspb.arith.UInt64(loValues[i], hiValues[j]);
  158. var b = new jspb.arith.UInt64(loValues[j], hiValues[i]);
  159. var c = a.add(b).sub(b);
  160. expect(c.hi).toEqual(a.hi);
  161. expect(c.lo).toEqual(a.lo);
  162. }
  163. }
  164. });
  165. /**
  166. * Tests 32-by-32 multiplication.
  167. */
  168. it('testMul32x32', function() {
  169. var testData = [
  170. // a b low(a*b) high(a*b)
  171. [0xc0abe2f8, 0x1607898a, 0x5de711b0, 0x109471b8],
  172. [0x915eb3cb, 0x4fb66d0e, 0xbd0d441a, 0x2d43d0bc],
  173. [0xfe4efe70, 0x80b48c37, 0xbcddea10, 0x7fdada0c],
  174. [0xe222fd4a, 0xe43d524a, 0xd5e0eb64, 0xc99d549c],
  175. [0xd171f469, 0xb94ebd01, 0x4be17969, 0x979bc4fa],
  176. [0x829cc1df, 0xe2598b38, 0xf4157dc8, 0x737c12ad],
  177. [0xf10c3767, 0x8382881e, 0x942b3612, 0x7bd428b8],
  178. [0xb0f6dd24, 0x232597e1, 0x079c98a4, 0x184bbce7],
  179. [0xfcdb05a7, 0x902f55bc, 0x636199a4, 0x8e69f412],
  180. [0x0dd0bfa9, 0x916e27b1, 0x6e2542d9, 0x07d92e65]
  181. ];
  182. for (var i = 0; i < testData.length; i++) {
  183. var a = testData[i][0] >>> 0;
  184. var b = testData[i][1] >>> 0;
  185. var cLow = testData[i][2] >>> 0;
  186. var cHigh = testData[i][3] >>> 0;
  187. var c = jspb.arith.UInt64.mul32x32(a, b);
  188. expect(c.lo).toEqual(cLow);
  189. expect(c.hi).toEqual(cHigh);
  190. }
  191. });
  192. /**
  193. * Tests 64-by-32 multiplication.
  194. */
  195. it('testMul', function() {
  196. // 64x32 bits produces 96 bits of product. The multiplication function under
  197. // test truncates the top 32 bits, so we compare against a 64-bit expected
  198. // product.
  199. var testData = [
  200. // low(a) high(a) low(a*b) high(a*b)
  201. [0xec10955b, 0x360eb168, 0x4b7f3f5b, 0xbfcb7c59, 0x9517da5f],
  202. [0x42b000fc, 0x9d101642, 0x6fa1ab72, 0x2584c438, 0x6a9e6d2b],
  203. [0xf42d4fb4, 0xae366403, 0xa65a1000, 0x92434000, 0x1ff978df],
  204. [0x17e2f56b, 0x25487693, 0xf13f98c7, 0x73794e2d, 0xa96b0c6a],
  205. [0x492f241f, 0x76c0eb67, 0x7377ac44, 0xd4336c3c, 0xfc4b1ebe],
  206. [0xd6b92321, 0xe184fa48, 0xd6e76904, 0x93141584, 0xcbf44da1],
  207. [0x4bf007ea, 0x968c0a9e, 0xf5e4026a, 0x4fdb1ae4, 0x61b9fb7d],
  208. [0x10a83be7, 0x2d685ba6, 0xc9e5fb7f, 0x2ad43499, 0x3742473d],
  209. [0x2f261829, 0x1aca681a, 0x3d3494e3, 0x8213205b, 0x283719f8],
  210. [0xe4f2ce21, 0x2e74b7bd, 0xd801b38b, 0xbc17feeb, 0xc6c44e0f]
  211. ];
  212. for (var i = 0; i < testData.length; i++) {
  213. var a = new jspb.arith.UInt64(testData[i][0], testData[i][1]);
  214. var prod = a.mul(testData[i][2]);
  215. expect(prod.lo).toEqual(testData[i][3]);
  216. expect(prod.hi).toEqual(testData[i][4]);
  217. }
  218. });
  219. /**
  220. * Tests 64-div-by-32 division.
  221. */
  222. it('testDiv', function() {
  223. // Compute a/b, yielding quot = a/b and rem = a%b.
  224. var testData = [
  225. // --- divisors in (0, 2^32-1) to test full divisor range
  226. // low(a) high(a) b low(quot) high(quot) rem
  227. [0x712443f1, 0xe85cefcc, 0xc1a7050b, 0x332c79ad, 0x00000001, 0x92ffa882],
  228. [0x11912915, 0xb2699eb5, 0x30467cbe, 0xb21b4be4, 0x00000003, 0x283465dd],
  229. [0x0d917982, 0x201f2a6e, 0x3f35bf03, 0x8217c8e4, 0x00000000, 0x153402d6],
  230. [0xa072c108, 0x74020c96, 0xc60568fd, 0x95f9613e, 0x00000000, 0x3f4676c2],
  231. [0xd845d5d8, 0xcdd235c4, 0x20426475, 0x6154e78b, 0x00000006, 0x202fb751],
  232. [0xa4dbf71f, 0x9e90465e, 0xf08e022f, 0xa8be947f, 0x00000000, 0xbe43b5ce],
  233. [0x3dbe627f, 0xa791f4b9, 0x28a5bd89, 0x1f5dfe93, 0x00000004, 0x02bf9ed4],
  234. [0x5c1c53ee, 0xccf5102e, 0x198576e7, 0x07e3ae31, 0x00000008, 0x02ea8fb7],
  235. [0xfef1e581, 0x04714067, 0xca6540c1, 0x059e73ec, 0x00000000, 0x31658095],
  236. [0x1e2dd90c, 0x13dd6667, 0x8b2184c3, 0x248d1a42, 0x00000000, 0x4ca6d0c6],
  237. // --- divisors in (0, 2^16-1) to test larger quotient high-words
  238. // low(a) high(a) b low(quot) high(quot) rem
  239. [0x86722b47, 0x2cd57c9a, 0x00003123, 0x2ae41b7a, 0x0000e995, 0x00000f99],
  240. [0x1dd7884c, 0xf5e839bc, 0x00009eeb, 0x5c886242, 0x00018c21, 0x000099b6],
  241. [0x5c53d625, 0x899fc7e5, 0x000087d7, 0xd625007a, 0x0001035c, 0x000019af],
  242. [0x6932d932, 0x9d0a5488, 0x000051fb, 0x9d976143, 0x0001ea63, 0x00004981],
  243. [0x4d18bb85, 0x0c92fb31, 0x00001d9f, 0x03265ab4, 0x00006cac, 0x000001b9],
  244. [0xbe756768, 0xdea67ccb, 0x00008a03, 0x58add442, 0x00019cff, 0x000056a2],
  245. [0xe2466f9a, 0x2521f114, 0x0000c350, 0xa0c0860d, 0x000030ab, 0x0000a48a],
  246. [0xf00ddad1, 0xe2f5446a, 0x00002cfc, 0x762697a6, 0x00050b96, 0x00000b69],
  247. [0xa879152a, 0x0a70e0a5, 0x00007cdf, 0xb44151b3, 0x00001567, 0x0000363d],
  248. [0x7179a74c, 0x46083fff, 0x0000253c, 0x4d39ba6e, 0x0001e17f, 0x00000f84]
  249. ];
  250. for (var i = 0; i < testData.length; i++) {
  251. var a = new jspb.arith.UInt64(testData[i][0], testData[i][1]);
  252. var result = a.div(testData[i][2]);
  253. var quotient = result[0];
  254. var remainder = result[1];
  255. expect(quotient.lo).toEqual(testData[i][3]);
  256. expect(quotient.hi).toEqual(testData[i][4]);
  257. expect(remainder.lo).toEqual(testData[i][5]);
  258. }
  259. });
  260. /**
  261. * Tests .toString() and .fromString().
  262. */
  263. it('testStrings', function() {
  264. var testData = [
  265. [0x5e84c935, 0xcae33d0e, '14619595947299359029'],
  266. [0x62b3b8b8, 0x93480544, '10612738313170434232'],
  267. [0x319bfb13, 0xc01c4172, '13843011313344445203'],
  268. [0x5b8a65fb, 0xa5885b31, '11927883880638080507'],
  269. [0x6bdb80f1, 0xb0d1b16b, '12741159895737008369'],
  270. [0x4b82b442, 0x2e0d8c97, '3318463081876730946'],
  271. [0x780d5208, 0x7d76752c, '9040542135845999112'],
  272. [0x2e46800f, 0x0993778d, '690026616168284175'],
  273. [0xf00a7e32, 0xcd8e3931, '14811839111111540274'],
  274. [0x1baeccd6, 0x923048c4, '10533999535534820566'],
  275. [0x03669d29, 0xbff3ab72, '13831587386756603177'],
  276. [0x2526073e, 0x01affc81, '121593346566522686'],
  277. [0xc24244e0, 0xd7f40d0e, '15561076969511732448'],
  278. [0xc56a341e, 0xa68b66a7, '12000798502816461854'],
  279. [0x8738d64d, 0xbfe78604, '13828168534871037517'],
  280. [0x5baff03b, 0xd7572aea, '15516918227177304123'],
  281. [0x4a843d8a, 0x864e132b, '9677693725920476554'],
  282. [0x25b4e94d, 0x22b54dc6, '2500990681505655117'],
  283. [0x6bbe664b, 0x55a5cc0e, '6171563226690381387'],
  284. [0xee916c81, 0xb00aabb3, '12685140089732426881']
  285. ];
  286. for (var i = 0; i < testData.length; i++) {
  287. var a = new jspb.arith.UInt64(testData[i][0], testData[i][1]);
  288. var roundtrip = jspb.arith.UInt64.fromString(a.toString());
  289. expect(roundtrip.lo).toEqual(a.lo);
  290. expect(roundtrip.hi).toEqual(a.hi);
  291. expect(a.toString()).toEqual(testData[i][2]);
  292. }
  293. });
  294. /**
  295. * Tests signed Int64s. These are built on UInt64s, so we only need to test
  296. * the explicit overrides: .toString() and .fromString().
  297. */
  298. it('testSignedInt64', function() {
  299. var testStrings = [
  300. '-7847499644178593666',
  301. '3771946501229139523',
  302. '2872856549054995060',
  303. '-5780049594274350904',
  304. '3383785956695105201',
  305. '2973055184857072610',
  306. '-3879428459215627206',
  307. '4589812431064156631',
  308. '8484075557333689940',
  309. '1075325817098092407',
  310. '-4346697501012292314',
  311. '2488620459718316637',
  312. '6112655187423520672',
  313. '-3655278273928612104',
  314. '3439154019435803196',
  315. '1004112478843763757',
  316. '-6587790776614368413',
  317. '664320065099714586',
  318. '4760412909973292912',
  319. '-7911903989602274672'
  320. ];
  321. for (var i = 0; i < testStrings.length; i++) {
  322. var roundtrip =
  323. jspb.arith.Int64.fromString(testStrings[i]).toString();
  324. expect(roundtrip).toEqual(testStrings[i]);
  325. }
  326. });
  327. });