Int64.hx 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. /*
  2. * Copyright (C)2005-2019 Haxe Foundation
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  20. * DEALINGS IN THE SOFTWARE.
  21. */
  22. package haxe;
  23. using haxe.Int64;
  24. /**
  25. A cross-platform signed 64-bit integer.
  26. Int64 instances can be created from two 32-bit words using `Int64.make()`.
  27. **/
  28. #if flash
  29. @:notNull
  30. #end
  31. @:transitive
  32. abstract Int64(__Int64) from __Int64 to __Int64 {
  33. private inline function new(x:__Int64)
  34. this = x;
  35. /**
  36. Makes a copy of `this` Int64.
  37. **/
  38. public inline function copy():Int64
  39. return make(high, low);
  40. /**
  41. Construct an Int64 from two 32-bit words `high` and `low`.
  42. **/
  43. public static inline function make(high:Int32, low:Int32):Int64
  44. return new Int64(new __Int64(high, low));
  45. /**
  46. Returns an Int64 with the value of the Int `x`.
  47. `x` is sign-extended to fill 64 bits.
  48. **/
  49. @:from public static inline function ofInt(x:Int):Int64
  50. #if lua return make((x : Int32) >> 31, (x : Int32)); #else return make(x >> 31, x); #end
  51. /**
  52. Returns an Int with the value of the Int64 `x`.
  53. Throws an exception if `x` cannot be represented in 32 bits.
  54. **/
  55. public static inline function toInt(x:Int64):Int {
  56. if (x.high != x.low >> 31)
  57. throw "Overflow";
  58. return x.low;
  59. }
  60. @:deprecated('haxe.Int64.is() is deprecated. Use haxe.Int64.isInt64() instead')
  61. inline public static function is(val:Dynamic):Bool {
  62. return isInt64(val);
  63. }
  64. /**
  65. Returns whether the value `val` is of type `haxe.Int64`
  66. **/
  67. inline public static function isInt64(val:Dynamic):Bool
  68. return Std.isOfType(val, __Int64);
  69. /**
  70. Returns the high 32-bit word of `x`.
  71. **/
  72. @:deprecated("Use high instead")
  73. public static inline function getHigh(x:Int64):Int32
  74. return x.high;
  75. /**
  76. Returns the low 32-bit word of `x`.
  77. **/
  78. @:deprecated("Use low instead")
  79. public static inline function getLow(x:Int64):Int32
  80. return x.low;
  81. /**
  82. Returns `true` if `x` is less than zero.
  83. **/
  84. public static inline function isNeg(x:Int64):Bool
  85. return x.high < 0;
  86. /**
  87. Returns `true` if `x` is exactly zero.
  88. **/
  89. public static inline function isZero(x:Int64):Bool
  90. return x == 0;
  91. /**
  92. Compares `a` and `b` in signed mode.
  93. Returns a negative value if `a < b`, positive if `a > b`,
  94. or 0 if `a == b`.
  95. **/
  96. public static inline function compare(a:Int64, b:Int64):Int {
  97. var v = a.high - b.high;
  98. v = if (v != 0) v else Int32.ucompare(a.low, b.low);
  99. return a.high < 0 ? (b.high < 0 ? v : -1) : (b.high >= 0 ? v : 1);
  100. }
  101. /**
  102. Compares `a` and `b` in unsigned mode.
  103. Returns a negative value if `a < b`, positive if `a > b`,
  104. or 0 if `a == b`.
  105. **/
  106. public static inline function ucompare(a:Int64, b:Int64):Int {
  107. var v = Int32.ucompare(a.high, b.high);
  108. return if (v != 0) v else Int32.ucompare(a.low, b.low);
  109. }
  110. /**
  111. Returns a signed decimal `String` representation of `x`.
  112. **/
  113. public static inline function toStr(x:Int64):String
  114. return x.toString();
  115. function toString():String {
  116. var i:Int64 = cast this;
  117. if (i == 0)
  118. return "0";
  119. var str = "";
  120. var neg = false;
  121. if (i.isNeg()) {
  122. neg = true;
  123. // i = -i; cannot negate here as --9223372036854775808 = -9223372036854775808
  124. }
  125. var ten:Int64 = 10;
  126. while (i != 0) {
  127. var r = i.divMod(ten);
  128. if (r.modulus.isNeg()) {
  129. str = Int64.neg(r.modulus).low + str;
  130. i = Int64.neg(r.quotient);
  131. } else {
  132. str = r.modulus.low + str;
  133. i = r.quotient;
  134. }
  135. }
  136. if (neg)
  137. str = "-" + str;
  138. return str;
  139. }
  140. public static inline function parseString(sParam:String):Int64 {
  141. return Int64Helper.parseString(sParam);
  142. }
  143. public static inline function fromFloat(f:Float):Int64 {
  144. return Int64Helper.fromFloat(f);
  145. }
  146. /**
  147. Performs signed integer division of `dividend` by `divisor`.
  148. Returns `{ quotient : Int64, modulus : Int64 }`.
  149. **/
  150. public static function divMod(dividend:Int64, divisor:Int64):{quotient:Int64, modulus:Int64} {
  151. // Handle special cases of 0 and 1
  152. if (divisor.high == 0) {
  153. switch (divisor.low) {
  154. case 0:
  155. throw "divide by zero";
  156. case 1:
  157. return {quotient: dividend.copy(), modulus: 0};
  158. }
  159. }
  160. var divSign = dividend.isNeg() != divisor.isNeg();
  161. var modulus = dividend.isNeg() ? -dividend : dividend.copy();
  162. divisor = divisor.isNeg() ? -divisor : divisor;
  163. var quotient:Int64 = 0;
  164. var mask:Int64 = 1;
  165. while (!divisor.isNeg()) {
  166. var cmp = ucompare(divisor, modulus);
  167. divisor <<= 1;
  168. mask <<= 1;
  169. if (cmp >= 0)
  170. break;
  171. }
  172. while (mask != 0) {
  173. if (ucompare(modulus, divisor) >= 0) {
  174. quotient |= mask;
  175. modulus -= divisor;
  176. }
  177. mask >>>= 1;
  178. divisor >>>= 1;
  179. }
  180. if (divSign)
  181. quotient = -quotient;
  182. if (dividend.isNeg())
  183. modulus = -modulus;
  184. return {
  185. quotient: quotient,
  186. modulus: modulus
  187. };
  188. }
  189. /**
  190. Returns the negative of `x`.
  191. **/
  192. @:op(-A) public static inline function neg(x:Int64):Int64 {
  193. var high = ~x.high;
  194. var low = -x.low;
  195. if (low == 0)
  196. high++;
  197. return make(high, low);
  198. }
  199. @:op(++A) private inline function preIncrement():Int64 {
  200. this = copy();
  201. this.low++;
  202. if (this.low == 0)
  203. this.high++;
  204. return cast this;
  205. }
  206. @:op(A++) private inline function postIncrement():Int64 {
  207. var ret = this;
  208. preIncrement();
  209. return ret;
  210. }
  211. @:op(--A) private inline function preDecrement():Int64 {
  212. this = copy();
  213. if (this.low == 0)
  214. this.high--;
  215. this.low--;
  216. return cast this;
  217. }
  218. @:op(A--) private inline function postDecrement():Int64 {
  219. var ret = this;
  220. preDecrement();
  221. return ret;
  222. }
  223. /**
  224. Returns the sum of `a` and `b`.
  225. **/
  226. @:op(A + B) public static inline function add(a:Int64, b:Int64):Int64 {
  227. var high = a.high + b.high;
  228. var low = a.low + b.low;
  229. if (Int32.ucompare(low, a.low) < 0)
  230. high++;
  231. return make(high, low);
  232. }
  233. @:op(A + B) @:commutative private static inline function addInt(a:Int64, b:Int):Int64
  234. return add(a, b);
  235. /**
  236. Returns `a` minus `b`.
  237. **/
  238. @:op(A - B) public static inline function sub(a:Int64, b:Int64):Int64 {
  239. var high = a.high - b.high;
  240. var low = a.low - b.low;
  241. if (Int32.ucompare(a.low, b.low) < 0)
  242. high--;
  243. return make(high, low);
  244. }
  245. @:op(A - B) private static inline function subInt(a:Int64, b:Int):Int64
  246. return sub(a, b);
  247. @:op(A - B) private static inline function intSub(a:Int, b:Int64):Int64
  248. return sub(a, b);
  249. /**
  250. Returns the product of `a` and `b`.
  251. **/
  252. @:op(A * B)
  253. public static #if !lua inline #end function mul(a:Int64, b:Int64):Int64 {
  254. var mask = 0xFFFF;
  255. var al = a.low & mask, ah = a.low >>> 16;
  256. var bl = b.low & mask, bh = b.low >>> 16;
  257. var p00 = al * bl;
  258. var p10 = ah * bl;
  259. var p01 = al * bh;
  260. var p11 = ah * bh;
  261. var low = p00;
  262. var high = p11 + (p01 >>> 16) + (p10 >>> 16);
  263. p01 <<= 16;
  264. low += p01;
  265. if (Int32.ucompare(low, p01) < 0)
  266. high++;
  267. p10 <<= 16;
  268. low += p10;
  269. if (Int32.ucompare(low, p10) < 0)
  270. high++;
  271. high += a.low * b.high + a.high * b.low;
  272. return make(high, low);
  273. }
  274. @:op(A * B) @:commutative private static inline function mulInt(a:Int64, b:Int):Int64
  275. return mul(a, b);
  276. /**
  277. Returns the quotient of `a` divided by `b`.
  278. **/
  279. @:op(A / B) public static inline function div(a:Int64, b:Int64):Int64
  280. return divMod(a, b).quotient;
  281. @:op(A / B) private static inline function divInt(a:Int64, b:Int):Int64
  282. return div(a, b);
  283. @:op(A / B) private static inline function intDiv(a:Int, b:Int64):Int64
  284. return div(a, b).toInt();
  285. /**
  286. Returns the modulus of `a` divided by `b`.
  287. **/
  288. @:op(A % B) public static inline function mod(a:Int64, b:Int64):Int64
  289. return divMod(a, b).modulus;
  290. @:op(A % B) private static inline function modInt(a:Int64, b:Int):Int64
  291. return mod(a, b).toInt();
  292. @:op(A % B) private static inline function intMod(a:Int, b:Int64):Int64
  293. return mod(a, b).toInt();
  294. /**
  295. Returns `true` if `a` is equal to `b`.
  296. **/
  297. @:op(A == B) public static inline function eq(a:Int64, b:Int64):Bool
  298. return a.high == b.high && a.low == b.low;
  299. @:op(A == B) @:commutative private static inline function eqInt(a:Int64, b:Int):Bool
  300. return eq(a, b);
  301. /**
  302. Returns `true` if `a` is not equal to `b`.
  303. **/
  304. @:op(A != B) public static inline function neq(a:Int64, b:Int64):Bool
  305. return a.high != b.high || a.low != b.low;
  306. @:op(A != B) @:commutative private static inline function neqInt(a:Int64, b:Int):Bool
  307. return neq(a, b);
  308. @:op(A < B) private static inline function lt(a:Int64, b:Int64):Bool
  309. return compare(a, b) < 0;
  310. @:op(A < B) private static inline function ltInt(a:Int64, b:Int):Bool
  311. return lt(a, b);
  312. @:op(A < B) private static inline function intLt(a:Int, b:Int64):Bool
  313. return lt(a, b);
  314. @:op(A <= B) private static inline function lte(a:Int64, b:Int64):Bool
  315. return compare(a, b) <= 0;
  316. @:op(A <= B) private static inline function lteInt(a:Int64, b:Int):Bool
  317. return lte(a, b);
  318. @:op(A <= B) private static inline function intLte(a:Int, b:Int64):Bool
  319. return lte(a, b);
  320. @:op(A > B) private static inline function gt(a:Int64, b:Int64):Bool
  321. return compare(a, b) > 0;
  322. @:op(A > B) private static inline function gtInt(a:Int64, b:Int):Bool
  323. return gt(a, b);
  324. @:op(A > B) private static inline function intGt(a:Int, b:Int64):Bool
  325. return gt(a, b);
  326. @:op(A >= B) private static inline function gte(a:Int64, b:Int64):Bool
  327. return compare(a, b) >= 0;
  328. @:op(A >= B) private static inline function gteInt(a:Int64, b:Int):Bool
  329. return gte(a, b);
  330. @:op(A >= B) private static inline function intGte(a:Int, b:Int64):Bool
  331. return gte(a, b);
  332. /**
  333. Returns the bitwise NOT of `a`.
  334. **/
  335. @:op(~A) private static inline function complement(a:Int64):Int64
  336. return make(~a.high, ~a.low);
  337. /**
  338. Returns the bitwise AND of `a` and `b`.
  339. **/
  340. @:op(A & B) public static inline function and(a:Int64, b:Int64):Int64
  341. return make(a.high & b.high, a.low & b.low);
  342. /**
  343. Returns the bitwise OR of `a` and `b`.
  344. **/
  345. @:op(A | B) public static inline function or(a:Int64, b:Int64):Int64
  346. return make(a.high | b.high, a.low | b.low);
  347. /**
  348. Returns the bitwise XOR of `a` and `b`.
  349. **/
  350. @:op(A ^ B) public static inline function xor(a:Int64, b:Int64):Int64
  351. return make(a.high ^ b.high, a.low ^ b.low);
  352. /**
  353. Returns `a` left-shifted by `b` bits.
  354. **/
  355. @:op(A << B) public static inline function shl(a:Int64, b:Int):Int64 {
  356. b &= 63;
  357. return if (b == 0) a.copy() else if (b < 32) make((a.high << b) | (a.low >>> (32 - b)), a.low << b) else make(a.low << (b - 32), 0);
  358. }
  359. /**
  360. Returns `a` right-shifted by `b` bits in signed mode.
  361. `a` is sign-extended.
  362. **/
  363. @:op(A >> B) public static inline function shr(a:Int64, b:Int):Int64 {
  364. b &= 63;
  365. return if (b == 0) a.copy() else if (b < 32) make(a.high >> b, (a.high << (32 - b)) | (a.low >>> b)); else make(a.high >> 31, a.high >> (b - 32));
  366. }
  367. /**
  368. Returns `a` right-shifted by `b` bits in unsigned mode.
  369. `a` is padded with zeroes.
  370. **/
  371. @:op(A >>> B) public static inline function ushr(a:Int64, b:Int):Int64 {
  372. b &= 63;
  373. return if (b == 0) a.copy() else if (b < 32) make(a.high >>> b, (a.high << (32 - b)) | (a.low >>> b)); else make(0, clamp(a.high >>> (b - 32)));
  374. }
  375. public var high(get, never):Int32;
  376. private inline function get_high()
  377. return this.high;
  378. private inline function set_high(x)
  379. return this.high = x;
  380. public var low(get, never):Int32;
  381. private inline function get_low()
  382. return this.low;
  383. private inline function set_low(x)
  384. return this.low = x;
  385. #if php
  386. static var extraBits:Int = php.Const.PHP_INT_SIZE * 8 - 32;
  387. #end
  388. #if !lua
  389. inline
  390. #end
  391. static function clamp(x:Int):Int {
  392. // force to-int conversion on platforms that require it
  393. #if js
  394. return x | 0;
  395. #elseif php
  396. // we might be on 64-bit php, so sign extend from 32-bit
  397. return (x << extraBits) >> extraBits;
  398. #elseif python
  399. return (python.Syntax.code("{0} % {1}", (x + python.Syntax.opPow(2, 31)), python.Syntax.opPow(2, 32)) : Int) - python.Syntax.opPow(2, 31);
  400. #elseif lua
  401. return lua.Boot.clampInt32(x);
  402. #else
  403. return x;
  404. #end
  405. }
  406. }
  407. /**
  408. This typedef will fool `@:coreApi` into thinking that we are using
  409. the same underlying type, even though it might be different on
  410. specific platforms.
  411. **/
  412. private typedef __Int64 = ___Int64;
  413. private class ___Int64 {
  414. public var high:Int32;
  415. public var low:Int32;
  416. public inline function new(high, low) {
  417. this.high = high;
  418. this.low = low;
  419. }
  420. /**
  421. We also define toString here to ensure we always get a pretty string
  422. when tracing or calling `Std.string`. This tends not to happen when
  423. `toString` is only in the abstract.
  424. **/
  425. public function toString():String
  426. return Int64.toStr(cast this);
  427. }