uint32.js 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. /**
  2. C-like unsigned 32 bits integers in Javascript
  3. Copyright (C) 2013, Pierre Curto
  4. MIT license
  5. */
  6. ;(function (root) {
  7. // Local cache for typical radices
  8. var radixPowerCache = {
  9. 36: UINT32( Math.pow(36, 5) )
  10. , 16: UINT32( Math.pow(16, 7) )
  11. , 10: UINT32( Math.pow(10, 9) )
  12. , 2: UINT32( Math.pow(2, 30) )
  13. }
  14. var radixCache = {
  15. 36: UINT32(36)
  16. , 16: UINT32(16)
  17. , 10: UINT32(10)
  18. , 2: UINT32(2)
  19. }
  20. /**
  21. * Represents an unsigned 32 bits integer
  22. * @constructor
  23. * @param {Number|String|Number} low bits | integer as a string | integer as a number
  24. * @param {Number|Number|Undefined} high bits | radix (optional, default=10)
  25. * @return
  26. */
  27. function UINT32 (l, h) {
  28. if ( !(this instanceof UINT32) )
  29. return new UINT32(l, h)
  30. this._low = 0
  31. this._high = 0
  32. this.remainder = null
  33. if (typeof h == 'undefined')
  34. return fromNumber.call(this, l)
  35. if (typeof l == 'string')
  36. return fromString.call(this, l, h)
  37. fromBits.call(this, l, h)
  38. }
  39. /**
  40. * Set the current _UINT32_ object with its low and high bits
  41. * @method fromBits
  42. * @param {Number} low bits
  43. * @param {Number} high bits
  44. * @return ThisExpression
  45. */
  46. function fromBits (l, h) {
  47. this._low = l | 0
  48. this._high = h | 0
  49. return this
  50. }
  51. UINT32.prototype.fromBits = fromBits
  52. /**
  53. * Set the current _UINT32_ object from a number
  54. * @method fromNumber
  55. * @param {Number} number
  56. * @return ThisExpression
  57. */
  58. function fromNumber (value) {
  59. this._low = value & 0xFFFF
  60. this._high = value >>> 16
  61. return this
  62. }
  63. UINT32.prototype.fromNumber = fromNumber
  64. /**
  65. * Set the current _UINT32_ object from a string
  66. * @method fromString
  67. * @param {String} integer as a string
  68. * @param {Number} radix (optional, default=10)
  69. * @return ThisExpression
  70. */
  71. function fromString (s, radix) {
  72. var value = parseInt(s, radix || 10)
  73. this._low = value & 0xFFFF
  74. this._high = value >>> 16
  75. return this
  76. }
  77. UINT32.prototype.fromString = fromString
  78. /**
  79. * Convert this _UINT32_ to a number
  80. * @method toNumber
  81. * @return {Number} the converted UINT32
  82. */
  83. UINT32.prototype.toNumber = function () {
  84. return (this._high * 65536) + this._low
  85. }
  86. /**
  87. * Convert this _UINT32_ to a string
  88. * @method toString
  89. * @param {Number} radix (optional, default=10)
  90. * @return {String} the converted UINT32
  91. */
  92. UINT32.prototype.toString = function (radix) {
  93. return this.toNumber().toString(radix || 10)
  94. }
  95. /**
  96. * Add two _UINT32_. The current _UINT32_ stores the result
  97. * @method add
  98. * @param {Object} other UINT32
  99. * @return ThisExpression
  100. */
  101. UINT32.prototype.add = function (other) {
  102. var a00 = this._low + other._low
  103. var a16 = a00 >>> 16
  104. a16 += this._high + other._high
  105. this._low = a00 & 0xFFFF
  106. this._high = a16 & 0xFFFF
  107. return this
  108. }
  109. /**
  110. * Subtract two _UINT32_. The current _UINT32_ stores the result
  111. * @method subtract
  112. * @param {Object} other UINT32
  113. * @return ThisExpression
  114. */
  115. UINT32.prototype.subtract = function (other) {
  116. //TODO inline
  117. return this.add( other.clone().negate() )
  118. }
  119. /**
  120. * Multiply two _UINT32_. The current _UINT32_ stores the result
  121. * @method multiply
  122. * @param {Object} other UINT32
  123. * @return ThisExpression
  124. */
  125. UINT32.prototype.multiply = function (other) {
  126. /*
  127. a = a00 + a16
  128. b = b00 + b16
  129. a*b = (a00 + a16)(b00 + b16)
  130. = a00b00 + a00b16 + a16b00 + a16b16
  131. a16b16 overflows the 32bits
  132. */
  133. var a16 = this._high
  134. var a00 = this._low
  135. var b16 = other._high
  136. var b00 = other._low
  137. /* Removed to increase speed under normal circumstances (i.e. not multiplying by 0 or 1)
  138. // this == 0 or other == 1: nothing to do
  139. if ((a00 == 0 && a16 == 0) || (b00 == 1 && b16 == 0)) return this
  140. // other == 0 or this == 1: this = other
  141. if ((b00 == 0 && b16 == 0) || (a00 == 1 && a16 == 0)) {
  142. this._low = other._low
  143. this._high = other._high
  144. return this
  145. }
  146. */
  147. var c16, c00
  148. c00 = a00 * b00
  149. c16 = c00 >>> 16
  150. c16 += a16 * b00
  151. c16 &= 0xFFFF // Not required but improves performance
  152. c16 += a00 * b16
  153. this._low = c00 & 0xFFFF
  154. this._high = c16 & 0xFFFF
  155. return this
  156. }
  157. /**
  158. * Divide two _UINT32_. The current _UINT32_ stores the result.
  159. * The remainder is made available as the _remainder_ property on
  160. * the _UINT32_ object. It can be null, meaning there are no remainder.
  161. * @method div
  162. * @param {Object} other UINT32
  163. * @return ThisExpression
  164. */
  165. UINT32.prototype.div = function (other) {
  166. if ( (other._low == 0) && (other._high == 0) ) throw Error('division by zero')
  167. // other == 1
  168. if (other._high == 0 && other._low == 1) {
  169. this.remainder = new UINT32(0)
  170. return this
  171. }
  172. // other > this: 0
  173. if ( other.gt(this) ) {
  174. this.remainder = this.clone()
  175. this._low = 0
  176. this._high = 0
  177. return this
  178. }
  179. // other == this: 1
  180. if ( this.eq(other) ) {
  181. this.remainder = new UINT32(0)
  182. this._low = 1
  183. this._high = 0
  184. return this
  185. }
  186. // Shift the divisor left until it is higher than the dividend
  187. var _other = other.clone()
  188. var i = -1
  189. while ( !this.lt(_other) ) {
  190. // High bit can overflow the default 16bits
  191. // Its ok since we right shift after this loop
  192. // The overflown bit must be kept though
  193. _other.shiftLeft(1, true)
  194. i++
  195. }
  196. // Set the remainder
  197. this.remainder = this.clone()
  198. // Initialize the current result to 0
  199. this._low = 0
  200. this._high = 0
  201. for (; i >= 0; i--) {
  202. _other.shiftRight(1)
  203. // If shifted divisor is smaller than the dividend
  204. // then subtract it from the dividend
  205. if ( !this.remainder.lt(_other) ) {
  206. this.remainder.subtract(_other)
  207. // Update the current result
  208. if (i >= 16) {
  209. this._high |= 1 << (i - 16)
  210. } else {
  211. this._low |= 1 << i
  212. }
  213. }
  214. }
  215. return this
  216. }
  217. /**
  218. * Negate the current _UINT32_
  219. * @method negate
  220. * @return ThisExpression
  221. */
  222. UINT32.prototype.negate = function () {
  223. var v = ( ~this._low & 0xFFFF ) + 1
  224. this._low = v & 0xFFFF
  225. this._high = (~this._high + (v >>> 16)) & 0xFFFF
  226. return this
  227. }
  228. /**
  229. * Equals
  230. * @method eq
  231. * @param {Object} other UINT32
  232. * @return {Boolean}
  233. */
  234. UINT32.prototype.equals = UINT32.prototype.eq = function (other) {
  235. return (this._low == other._low) && (this._high == other._high)
  236. }
  237. /**
  238. * Greater than (strict)
  239. * @method gt
  240. * @param {Object} other UINT32
  241. * @return {Boolean}
  242. */
  243. UINT32.prototype.greaterThan = UINT32.prototype.gt = function (other) {
  244. if (this._high > other._high) return true
  245. if (this._high < other._high) return false
  246. return this._low > other._low
  247. }
  248. /**
  249. * Less than (strict)
  250. * @method lt
  251. * @param {Object} other UINT32
  252. * @return {Boolean}
  253. */
  254. UINT32.prototype.lessThan = UINT32.prototype.lt = function (other) {
  255. if (this._high < other._high) return true
  256. if (this._high > other._high) return false
  257. return this._low < other._low
  258. }
  259. /**
  260. * Bitwise OR
  261. * @method or
  262. * @param {Object} other UINT32
  263. * @return ThisExpression
  264. */
  265. UINT32.prototype.or = function (other) {
  266. this._low |= other._low
  267. this._high |= other._high
  268. return this
  269. }
  270. /**
  271. * Bitwise AND
  272. * @method and
  273. * @param {Object} other UINT32
  274. * @return ThisExpression
  275. */
  276. UINT32.prototype.and = function (other) {
  277. this._low &= other._low
  278. this._high &= other._high
  279. return this
  280. }
  281. /**
  282. * Bitwise NOT
  283. * @method not
  284. * @return ThisExpression
  285. */
  286. UINT32.prototype.not = function() {
  287. this._low = ~this._low & 0xFFFF
  288. this._high = ~this._high & 0xFFFF
  289. return this
  290. }
  291. /**
  292. * Bitwise XOR
  293. * @method xor
  294. * @param {Object} other UINT32
  295. * @return ThisExpression
  296. */
  297. UINT32.prototype.xor = function (other) {
  298. this._low ^= other._low
  299. this._high ^= other._high
  300. return this
  301. }
  302. /**
  303. * Bitwise shift right
  304. * @method shiftRight
  305. * @param {Number} number of bits to shift
  306. * @return ThisExpression
  307. */
  308. UINT32.prototype.shiftRight = UINT32.prototype.shiftr = function (n) {
  309. if (n > 16) {
  310. this._low = this._high >> (n - 16)
  311. this._high = 0
  312. } else if (n == 16) {
  313. this._low = this._high
  314. this._high = 0
  315. } else {
  316. this._low = (this._low >> n) | ( (this._high << (16-n)) & 0xFFFF )
  317. this._high >>= n
  318. }
  319. return this
  320. }
  321. /**
  322. * Bitwise shift left
  323. * @method shiftLeft
  324. * @param {Number} number of bits to shift
  325. * @param {Boolean} allow overflow
  326. * @return ThisExpression
  327. */
  328. UINT32.prototype.shiftLeft = UINT32.prototype.shiftl = function (n, allowOverflow) {
  329. if (n > 16) {
  330. this._high = this._low << (n - 16)
  331. this._low = 0
  332. if (!allowOverflow) {
  333. this._high &= 0xFFFF
  334. }
  335. } else if (n == 16) {
  336. this._high = this._low
  337. this._low = 0
  338. } else {
  339. this._high = (this._high << n) | (this._low >> (16-n))
  340. this._low = (this._low << n) & 0xFFFF
  341. if (!allowOverflow) {
  342. // Overflow only allowed on the high bits...
  343. this._high &= 0xFFFF
  344. }
  345. }
  346. return this
  347. }
  348. /**
  349. * Bitwise rotate left
  350. * @method rotl
  351. * @param {Number} number of bits to rotate
  352. * @return ThisExpression
  353. */
  354. UINT32.prototype.rotateLeft = UINT32.prototype.rotl = function (n) {
  355. var v = (this._high << 16) | this._low
  356. v = (v << n) | (v >>> (32 - n))
  357. this._low = v & 0xFFFF
  358. this._high = v >>> 16
  359. return this
  360. }
  361. /**
  362. * Bitwise rotate right
  363. * @method rotr
  364. * @param {Number} number of bits to rotate
  365. * @return ThisExpression
  366. */
  367. UINT32.prototype.rotateRight = UINT32.prototype.rotr = function (n) {
  368. var v = (this._high << 16) | this._low
  369. v = (v >>> n) | (v << (32 - n))
  370. this._low = v & 0xFFFF
  371. this._high = v >>> 16
  372. return this
  373. }
  374. /**
  375. * Clone the current _UINT32_
  376. * @method clone
  377. * @return {Object} cloned UINT32
  378. */
  379. UINT32.prototype.clone = function () {
  380. return new UINT32(this._low, this._high)
  381. }
  382. if (typeof define != 'undefined' && define.amd) {
  383. // AMD / RequireJS
  384. define([], function () {
  385. return UINT32
  386. })
  387. } else if (typeof module != 'undefined' && module.exports) {
  388. // Node.js
  389. module.exports = UINT32
  390. } else {
  391. // Browser
  392. root['UINT32'] = UINT32
  393. }
  394. })(this)