1. my class Rat { ... }
  2. my class X::Cannot::Capture { ... }
  3. my class X::Numeric::DivideByZero { ... }
  4. my class X::NYI::BigInt { ... }
  5. my class Int { ... }
  6. my subset UInt of Int where {not .defined or $_ >= 0};
  7. my class Int does Real { # declared in BOOTSTRAP
  8. # class Int is Cool
  9. # has bigint $!value is box_target;
  10. multi method WHICH(Int:D:) {
  11. nqp::box_s(
  12. nqp::concat(
  13. nqp::if(
  14. nqp::eqaddr(self.WHAT,Int),
  15. 'Int|',
  16. nqp::concat(nqp::unbox_s(self.^name), '|')
  17. ),
  18. nqp::tostr_I(self)
  19. ),
  20. ValueObjAt
  21. )
  22. }
  23. proto method new(|) {*}
  24. multi method new( \value) { self.new: value.Int }
  25. multi method new(int \value) {
  26. # rebox the value, so we get rid of any potential mixins
  27. nqp::fromI_I(nqp::decont(value), self)
  28. }
  29. multi method new(Int:D \value = 0) {
  30. # rebox the value, so we get rid of any potential mixins
  31. nqp::fromI_I(nqp::decont(value), self)
  32. }
  33. multi method perl(Int:D:) {
  34. self.Str;
  35. }
  36. multi method Bool(Int:D:) {
  37. nqp::p6bool(nqp::bool_I(self));
  38. }
  39. method Capture() { die X::Cannot::Capture.new: :what(self) }
  40. method Int() { self }
  41. multi method Str(Int:D:) {
  42. nqp::p6box_s(nqp::tostr_I(self));
  43. }
  44. method Num(Int:D:) {
  45. nqp::p6box_n(nqp::tonum_I(self));
  46. }
  47. method Rat(Int:D: $?) {
  48. Rat.new(self, 1);
  49. }
  50. method FatRat(Int:D: $?) {
  51. FatRat.new(self, 1);
  52. }
  53. method abs(Int:D:) {
  54. nqp::abs_I(self, Int)
  55. }
  56. method Bridge(Int:D:) {
  57. nqp::p6box_n(nqp::tonum_I(self));
  58. }
  59. method chr(Int:D:) {
  60. nqp::if(
  61. nqp::isbig_I(self),
  62. die("chr codepoint %i (0x%X) is too large".sprintf(self, self)),
  63. nqp::p6box_s(nqp::chr(nqp::unbox_i(self)))
  64. )
  65. }
  66. method sqrt(Int:D:) { nqp::p6box_n(nqp::sqrt_n(nqp::tonum_I(self))) }
  67. proto method base(|) {*}
  68. multi method base(Int:D: Int:D $base) {
  69. 2 <= $base <= 36
  70. ?? nqp::p6box_s(nqp::base_I(self,nqp::unbox_i($base)))
  71. !! Failure.new(X::OutOfRange.new(
  72. what => "base argument to base", :got($base), :range<2..36>))
  73. }
  74. multi method base(Int:D: Int(Cool) $base, $digits?) {
  75. 2 <= $base <= 36
  76. ?? $digits && ! nqp::istype($digits, Whatever)
  77. ?? $digits < 0
  78. ?? Failure.new(X::OutOfRange.new(
  79. :what('digits argument to base'),:got($digits),:range<0..1073741824>))
  80. !! nqp::p6box_s(nqp::base_I(self,nqp::unbox_i($base)))
  81. ~ '.'
  82. ~ '0' x $digits
  83. !! nqp::p6box_s(nqp::base_I(self,nqp::unbox_i($base)))
  84. !! Failure.new(X::OutOfRange.new(
  85. :what('base argument to base'),:got($base),:range<2..36>))
  86. }
  87. # If self is Int, we assume mods are Ints also. (div fails otherwise.)
  88. # If do-not-want, user should cast invocant to proper domain.
  89. method polymod(Int:D: +@mods) {
  90. fail X::OutOfRange.new(
  91. :what('invocant to polymod'), :got(self), :range<0..^Inf>
  92. ) if self < 0;
  93. gather {
  94. my $more = self;
  95. if @mods.is-lazy {
  96. for @mods -> $mod {
  97. $more
  98. ?? $mod
  99. ?? take $more mod $mod
  100. !! Failure.new(X::Numeric::DivideByZero.new:
  101. using => 'polymod', numerator => $more)
  102. !! last;
  103. $more = $more div $mod;
  104. }
  105. take $more if $more;
  106. }
  107. else {
  108. for @mods -> $mod {
  109. $mod
  110. ?? take $more mod $mod
  111. !! Failure.new(X::Numeric::DivideByZero.new:
  112. using => 'polymod', numerator => $more);
  113. $more = $more div $mod;
  114. }
  115. take $more;
  116. }
  117. }
  118. }
  119. method expmod(Int:D: Int:D \base, Int:D \mod) {
  120. nqp::expmod_I(self, nqp::decont(base), nqp::decont(mod), Int);
  121. }
  122. method is-prime(--> Bool:D) { nqp::p6bool(nqp::isprime_I(self,100)) }
  123. method floor(Int:D:) { self }
  124. method ceiling(Int:D:) { self }
  125. proto method round(|) {*}
  126. multi method round(Int:D:) { self }
  127. multi method round(Int:D: Real(Cool) $scale) { (self / $scale + 1/2).floor * $scale }
  128. method lsb(Int:D:) {
  129. return Nil if self == 0;
  130. my $lsb = 0;
  131. my $x = self.abs;
  132. while $x +& 0xff == 0 { $lsb += 8; $x +>= 8; }
  133. while $x +& 0x01 == 0 { ++$lsb; $x +>= 1; }
  134. $lsb;
  135. }
  136. method msb(Int:D:) {
  137. return Nil if self == 0;
  138. return 0 if self == -1;
  139. my $msb = 0;
  140. my $x = self;
  141. $x = ($x + 1) * -2 if $x < 0; # handle negative conversions
  142. while $x > 0xff { $msb += 8; $x +>= 8; }
  143. if $x > 0x0f { $msb += 4; $x +>= 4; }
  144. if $x +& 0x8 { $msb += 3; }
  145. elsif $x +& 0x4 { $msb += 2; }
  146. elsif $x +& 0x2 { $msb += 1; }
  147. $msb;
  148. }
  149. method narrow(Int:D:) { self }
  150. method Range(Int:U:) {
  151. given self {
  152. when int { $?BITS == 64 ?? int64.Range !! int32.Range }
  153. when uint { $?BITS == 64 ?? uint64.Range !! uint32.Range }
  154. when int64 { Range.new(-9223372036854775808, 9223372036854775807) }
  155. when int32 { Range.new( -2147483648, 2147483647 ) }
  156. when int16 { Range.new( -32768, 32767 ) }
  157. when int8 { Range.new( -128, 127 ) }
  158. # Bring back in a future Perl 6 version, or just put on the type object
  159. #when int4 { Range.new( -8, 7 ) }
  160. #when int2 { Range.new( -2, 1 ) }
  161. #when int1 { Range.new( -1, 0 ) }
  162. when uint64 { Range.new( 0, 18446744073709551615 ) }
  163. when uint32 { Range.new( 0, 4294967295 ) }
  164. when uint16 { Range.new( 0, 65535 ) }
  165. when uint8 { Range.new( 0, 255 ) }
  166. when byte { Range.new( 0, 255 ) }
  167. # Bring back in a future Perl 6 version, or just put on the type object
  168. #when uint4 { Range.new( 0, 15 ) }
  169. #when uint2 { Range.new( 0, 3 ) }
  170. #when uint1 { Range.new( 0, 1 ) }
  171. default { # some other kind of Int
  172. .^name eq 'UInt'
  173. ?? Range.new( 0, Inf, :excludes-max )
  174. !! Range.new( -Inf, Inf, :excludes-min, :excludes-max )
  175. }
  176. }
  177. }
  178. }
  179. multi sub prefix:<++>(Int:D $a is rw) {
  180. $a = nqp::add_I(nqp::decont($a), 1, Int);
  181. }
  182. multi sub prefix:<++>(int $a is rw) {
  183. $a = nqp::add_i($a, 1);
  184. }
  185. multi sub prefix:<-->(Int:D $a is rw) {
  186. $a = nqp::sub_I(nqp::decont($a), 1, Int);
  187. }
  188. multi sub prefix:<-->(int $a is rw) {
  189. $a = nqp::sub_i($a, 1);
  190. }
  191. multi sub postfix:<++>(Int:D $a is rw) {
  192. my \b := nqp::decont($a);
  193. $a = nqp::add_I(b, 1, Int);
  194. b
  195. }
  196. multi sub postfix:<++>(int $a is rw) {
  197. my int $b = $a;
  198. $a = nqp::add_i($b, 1);
  199. $b
  200. }
  201. multi sub postfix:<-->(Int:D $a is rw) {
  202. my \b := nqp::decont($a);
  203. $a = nqp::sub_I(b, 1, Int);
  204. b
  205. }
  206. multi sub postfix:<-->(int $a is rw) {
  207. my int $b = $a;
  208. $a = nqp::sub_i($b, 1);
  209. $b
  210. }
  211. multi sub prefix:<->(Int:D \a --> Int:D) {
  212. nqp::neg_I(nqp::decont(a), Int);
  213. }
  214. multi sub prefix:<->(int $a --> int) {
  215. nqp::neg_i($a)
  216. }
  217. multi sub abs(Int:D \a --> Int:D) {
  218. nqp::abs_I(nqp::decont(a), Int);
  219. }
  220. multi sub abs(int $a --> int) {
  221. nqp::abs_i($a)
  222. }
  223. multi sub infix:<+>(Int:D \a, Int:D \b --> Int:D) {
  224. nqp::add_I(nqp::decont(a), nqp::decont(b), Int);
  225. }
  226. multi sub infix:<+>(int $a, int $b --> int) {
  227. nqp::add_i($a, $b)
  228. }
  229. multi sub infix:<->(Int:D \a, Int:D \b --> Int:D) {
  230. nqp::sub_I(nqp::decont(a), nqp::decont(b), Int);
  231. }
  232. multi sub infix:<->(int $a, int $b --> int) {
  233. nqp::sub_i($a, $b)
  234. }
  235. multi sub infix:<*>(Int:D \a, Int:D \b --> Int:D) {
  236. nqp::mul_I(nqp::decont(a), nqp::decont(b), Int);
  237. }
  238. multi sub infix:<*>(int $a, int $b --> int) {
  239. nqp::mul_i($a, $b);
  240. }
  241. multi sub infix:<div>(Int:D \a, Int:D \b) {
  242. b
  243. ?? nqp::div_I(nqp::decont(a), nqp::decont(b), Int)
  244. !! Failure.new(X::Numeric::DivideByZero.new(:using<div>, :numerator(a)))
  245. }
  246. multi sub infix:<div>(int $a, int $b --> int) {
  247. # relies on opcode or hardware to detect division by 0
  248. nqp::div_i($a, $b)
  249. }
  250. multi sub infix:<%>(Int:D \a, Int:D \b --> Int:D) {
  251. nqp::if(
  252. nqp::isbig_I(nqp::decont(a)) || nqp::isbig_I(nqp::decont(b)),
  253. nqp::if(
  254. b,
  255. nqp::mod_I(nqp::decont(a),nqp::decont(b),Int),
  256. Failure.new(X::Numeric::DivideByZero.new(:using<%>, :numerator(a)))
  257. ),
  258. nqp::if(
  259. nqp::isne_i(b,0),
  260. nqp::mod_i( # quick fix RT #128318
  261. nqp::add_i(nqp::mod_i(nqp::decont(a),nqp::decont(b)),b),
  262. nqp::decont(b)
  263. ),
  264. Failure.new(X::Numeric::DivideByZero.new(:using<%>, :numerator(a)))
  265. )
  266. )
  267. }
  268. multi sub infix:<%>(int $a, int $b --> int) {
  269. # relies on opcode or hardware to detect division by 0
  270. nqp::mod_i(nqp::add_i(nqp::mod_i($a,$b),$b),$b) # quick fix RT #128318
  271. }
  272. multi sub infix:<**>(Int:D \a, Int:D \b) {
  273. my $power := nqp::pow_I(nqp::decont(a), nqp::decont(b >= 0 ?? b !! -b), Num, Int);
  274. # when a**b is too big nqp::pow_I returns Inf
  275. nqp::istype($power, Num)
  276. ?? Failure.new(
  277. b >= 0 ?? X::Numeric::Overflow.new !! X::Numeric::Underflow.new
  278. ) !! b >= 0 ?? $power
  279. !! ($power := 1 / $power) == 0 && a != 0
  280. ?? Failure.new(X::Numeric::Underflow.new)
  281. !! $power;
  282. }
  283. multi sub infix:<**>(int $a, int $b --> int) {
  284. nqp::pow_i($a, $b);
  285. }
  286. multi sub infix:<lcm>(Int:D \a, Int:D \b --> Int:D) {
  287. nqp::lcm_I(nqp::decont(a), nqp::decont(b), Int);
  288. }
  289. multi sub infix:<lcm>(int $a, int $b --> int) {
  290. nqp::lcm_i($a, $b)
  291. }
  292. multi sub infix:<gcd>(Int:D \a, Int:D \b --> Int:D) {
  293. nqp::gcd_I(nqp::decont(a), nqp::decont(b), Int);
  294. }
  295. multi sub infix:<gcd>(int $a, int $b --> int) {
  296. nqp::gcd_i($a, $b)
  297. }
  298. multi sub infix:<===>(Int:D \a, Int:D \b) {
  299. nqp::p6bool(
  300. nqp::eqaddr(a.WHAT,b.WHAT)
  301. && nqp::iseq_I(nqp::decont(a), nqp::decont(b))
  302. )
  303. }
  304. multi sub infix:<===>(int $a, int $b) {
  305. # hey, the optimizer is smart enough to figure that one out for us, no?
  306. $a == $b
  307. }
  308. multi sub infix:<==>(Int:D \a, Int:D \b) {
  309. nqp::p6bool(nqp::iseq_I(nqp::decont(a), nqp::decont(b)))
  310. }
  311. multi sub infix:<==>(int $a, int $b) {
  312. nqp::p6bool(nqp::iseq_i($a, $b))
  313. }
  314. multi sub infix:<!=>(int $a, int $b) { nqp::p6bool(nqp::isne_i($a, $b)) }
  315. multi sub infix:«<»(Int:D \a, Int:D \b) {
  316. nqp::p6bool(nqp::islt_I(nqp::decont(a), nqp::decont(b)))
  317. }
  318. multi sub infix:«<»(int $a, int $b) {
  319. nqp::p6bool(nqp::islt_i($a, $b))
  320. }
  321. multi sub infix:«<=»(Int:D \a, Int:D \b) {
  322. nqp::p6bool(nqp::isle_I(nqp::decont(a), nqp::decont(b)))
  323. }
  324. multi sub infix:«<=»(int $a, int $b) {
  325. nqp::p6bool(nqp::isle_i($a, $b))
  326. }
  327. multi sub infix:«>»(Int:D \a, Int:D \b) {
  328. nqp::p6bool(nqp::isgt_I(nqp::decont(a), nqp::decont(b)))
  329. }
  330. multi sub infix:«>»(int $a, int $b) {
  331. nqp::p6bool(nqp::isgt_i($a, $b))
  332. }
  333. multi sub infix:«>=»(Int:D \a, Int:D \b) {
  334. nqp::p6bool(nqp::isge_I(nqp::decont(a), nqp::decont(b)))
  335. }
  336. multi sub infix:«>=»(int $a, int $b) {
  337. nqp::p6bool(nqp::isge_i($a, $b))
  338. }
  339. multi sub infix:<+|>(Int:D \a, Int:D \b) {
  340. nqp::bitor_I(nqp::decont(a), nqp::decont(b), Int)
  341. }
  342. multi sub infix:<+|>(int $a, int $b) {
  343. nqp::bitor_i($a, $b)
  344. }
  345. multi sub infix:<+&>(Int:D \a, Int:D \b) {
  346. nqp::bitand_I(nqp::decont(a), nqp::decont(b), Int)
  347. }
  348. multi sub infix:<+&>(int $a, int $b) {
  349. nqp::bitand_i($a, $b)
  350. }
  351. multi sub infix:<+^>(Int:D \a, Int:D \b) {
  352. nqp::bitxor_I(nqp::decont(a), nqp::decont(b), Int)
  353. }
  354. multi sub infix:<+^>(int $a, int $b) {
  355. nqp::bitxor_i($a, $b);
  356. }
  357. multi sub infix:«+<»(Int:D \a, Int:D \b --> Int:D) {
  358. nqp::bitshiftl_I(nqp::decont(a), nqp::unbox_i(b), Int)
  359. }
  360. multi sub infix:«+<»(int $a, int $b) {
  361. nqp::bitshiftl_i($a, $b);
  362. }
  363. multi sub infix:«+>»(Int:D \a, Int:D \b --> Int:D) {
  364. nqp::bitshiftr_I(nqp::decont(a), nqp::unbox_i(b), Int)
  365. }
  366. multi sub infix:«+>»(int $a, int $b) {
  367. nqp::bitshiftr_i($a, $b)
  368. }
  369. multi sub prefix:<+^>(Int:D \a) {
  370. nqp::bitneg_I(nqp::decont(a), Int);
  371. }
  372. multi sub prefix:<+^>(int $a) {
  373. nqp::bitneg_i($a);
  374. }
  375. proto sub chr($) is pure {*}
  376. multi sub chr(Int:D \x --> Str:D) { x.chr }
  377. multi sub chr(Cool \x --> Str:D) { x.Int.chr }
  378. multi sub chr(int $x --> str) {
  379. nqp::chr($x);
  380. }
  381. proto sub is-prime(|) is pure {*}
  382. multi sub is-prime(\x) { x.is-prime }
  383. proto sub expmod($, $, $) is pure {*}
  384. multi sub expmod(Int:D \base, Int:D \exp, Int:D \mod) {
  385. nqp::expmod_I(nqp::decont(base), nqp::decont(exp), nqp::decont(mod), Int);
  386. }
  387. multi sub expmod(\base, \exp, \mod) {
  388. nqp::expmod_I(nqp::decont(base.Int), nqp::decont(exp.Int), nqp::decont(mod.Int), Int);
  389. }
  390. proto sub lsb($) {*}
  391. multi sub lsb(Int:D \i) { i.lsb }
  392. proto sub msb($) {*}
  393. multi sub msb(Int:D \i) { i.msb }