1. my class Complex { ... }
  2. my role Real does Numeric {
  3. method Rat(Real:D: Real $epsilon = 1.0e-6) { self.Bridge.Rat($epsilon) }
  4. method abs() { self < 0 ?? -self !! self }
  5. method sign(Real:D:) { self > 0 ?? 1 !! self < 0 ?? -1 !! +self }
  6. method conj(Real:D:) { self }
  7. method sqrt() { self.Bridge.sqrt }
  8. method rand() { self.Bridge.rand }
  9. method sin() { self.Bridge.sin }
  10. method asin() { self.Bridge.asin }
  11. method cos() { self.Bridge.cos }
  12. method acos() { self.Bridge.acos }
  13. method tan() { self.Bridge.tan }
  14. method atan() { self.Bridge.atan }
  15. proto method atan2(|) {*}
  16. multi method atan2(Real $x = 1e0) { self.Bridge.atan2($x.Bridge) }
  17. multi method atan2(Cool $x = 1e0) { self.Bridge.atan2($x.Numeric.Bridge) }
  18. method sec() { self.Bridge.sec }
  19. method asec() { self.Bridge.asec }
  20. method cosec() { self.Bridge.cosec }
  21. method acosec() { self.Bridge.acosec }
  22. method cotan() { self.Bridge.cotan }
  23. method acotan() { self.Bridge.acotan }
  24. method sinh() { self.Bridge.sinh }
  25. method asinh() { self.Bridge.asinh }
  26. method cosh() { self.Bridge.cosh }
  27. method acosh() { self.Bridge.acosh }
  28. method tanh() { self.Bridge.tanh }
  29. method atanh() { self.Bridge.atanh }
  30. method sech() { self.Bridge.sech }
  31. method asech() { self.Bridge.asech }
  32. method cosech() { self.Bridge.cosech }
  33. method acosech() { self.Bridge.acosech }
  34. method cotanh() { self.Bridge.cotanh }
  35. method acotanh() { self.Bridge.acotanh }
  36. method floor() { self.Bridge.floor }
  37. method ceiling() { self.Bridge.ceiling }
  38. proto method round(|) { * }
  39. multi method round(Real:D:) {
  40. (self + 1/2).floor; # Rat NYI here, so no .5
  41. }
  42. multi method round(Real:D: Real() $scale) {
  43. (self / $scale + 1/2).floor * $scale;
  44. }
  45. method unpolar(Real $angle) {
  46. Complex.new(self * $angle.cos, self * $angle.sin);
  47. }
  48. method cis() {
  49. Complex.new(self.cos, self.sin);
  50. }
  51. method Complex() { Complex.new(self.Num, 0e0) }
  52. proto method log(|) {*}
  53. multi method log(Real:D: ) { self.Bridge.log }
  54. multi method log(Real:D: Real $base) { self.Bridge.log($base.Bridge) }
  55. proto method exp(|) {*}
  56. multi method exp(Real:D: ) { self.Bridge.exp }
  57. method truncate(Real:D:) {
  58. self == 0 ?? 0 !! self < 0 ?? self.ceiling !! self.floor
  59. }
  60. method isNaN { Bool::False }
  61. method polymod(Real:D: +@mods) {
  62. my $more = self;
  63. my $lazy = @mods.is-lazy;
  64. fail X::OutOfRange.new(
  65. :what('invocant to polymod'), :got($more), :range<0..Inf>
  66. ) if $more < 0;
  67. gather {
  68. for @mods -> $mod {
  69. last if $lazy and not $more;
  70. Failure.new(X::Numeric::DivideByZero.new:
  71. using => 'polymod', numerator => $more
  72. ) unless $mod;
  73. take my $rem = $more % $mod;
  74. $more -= $rem;
  75. $more /= $mod;
  76. }
  77. take $more if ($lazy and $more) or not $lazy;
  78. }
  79. }
  80. method base(Int:D $base, $digits? is copy) {
  81. $digits = Nil if nqp::istype($digits, Whatever);
  82. fail X::OutOfRange.new(
  83. :what('digits argument to base'), :got($digits),
  84. :range<0..1073741824>
  85. ) if $digits.defined and $digits < 0;
  86. my $prec = $digits // 1e8.log($base.Num).Int;
  87. my Int $int_part = self.Int;
  88. my $frac = abs(self - $int_part);
  89. my @frac_digits;
  90. my @conversion := <0 1 2 3 4 5 6 7 8 9
  91. A B C D E F G H I J
  92. K L M N O P Q R S T
  93. U V W X Y Z>;
  94. for ^$prec {
  95. last unless $digits // $frac;
  96. $frac = $frac * $base;
  97. push @frac_digits, $frac.Int;
  98. $frac = $frac - $frac.Int;
  99. }
  100. if 2 * $frac >= 1 {
  101. if @frac_digits {
  102. for @frac_digits-1 ... 0 -> $x {
  103. last if ++@frac_digits[$x] < $base;
  104. @frac_digits[$x] = 0;
  105. $int_part++ if $x == 0
  106. }
  107. }
  108. else {
  109. $int_part++;
  110. }
  111. }
  112. my Str $r = $int_part.base($base);
  113. $r ~= '.' ~ @conversion[@frac_digits].join if @frac_digits;
  114. # if $int_part is 0, $int_part.base doesn't see the sign of self
  115. $int_part == 0 && self < 0 ?? '-' ~ $r !! $r;
  116. }
  117. method Real(Real:D:) { self }
  118. method Bridge(Real:D:) { self.Num }
  119. method Int(Real:D:) { self.Bridge.Int }
  120. method Num(Real:D:) { self.Bridge.Num }
  121. multi method Str(Real:D:) { self.Bridge.Str }
  122. }
  123. proto sub cis($) {*}
  124. multi sub cis(Real $a) { $a.cis }
  125. multi sub infix:<+>(Real \a, Real \b) { a.Bridge + b.Bridge }
  126. multi sub infix:<->(Real \a, Real \b) { a.Bridge - b.Bridge }
  127. multi sub infix:<*>(Real \a, Real \b) { a.Bridge * b.Bridge }
  128. multi sub infix:</>(Real \a, Real \b) { a.Bridge / b.Bridge }
  129. multi sub infix:<%>(Real \a, Real \b) { a.Bridge % b.Bridge }
  130. multi sub infix:<**>(Real \a, Real \b) { a.Bridge ** b.Bridge }
  131. multi sub infix:«<=>»(Real \a, Real \b) { a.Bridge <=> b.Bridge }
  132. multi sub infix:<==>(Real \a, Real \b) { a.Bridge == b.Bridge }
  133. multi sub infix:«<»(Real \a, Real \b) { a.Bridge < b.Bridge }
  134. multi sub infix:«<=»(Real \a, Real \b) { a.Bridge <= b.Bridge }
  135. multi sub infix:«>»(Real \a, Real \b) { a.Bridge > b.Bridge }
  136. multi sub infix:«>=»(Real \a, Real \b) { a.Bridge >= b.Bridge }
  137. multi sub prefix:<->(Real:D \a) { -a.Bridge }
  138. # NOTE: According to the spec, infix:<mod> is "Not coercive,
  139. # so fails on differing types." Thus no casts here.
  140. proto sub infix:<mod>($, $) is pure {*}
  141. multi sub infix:<mod>(Real $a, Real $b) {
  142. $a - ($a div $b) * $b;
  143. }
  144. multi sub abs(Real \a) {
  145. a < 0 ?? -a !! a;
  146. }
  147. proto sub truncate($) {*}
  148. multi sub truncate(Real:D $x) { $x.truncate }
  149. multi sub truncate(Cool:D $x) { $x.Numeric.truncate }
  150. proto sub atan2($, $?) { * }
  151. multi sub atan2(Real \a, Real \b = 1e0) { a.Bridge.atan2(b.Bridge) }
  152. # should really be (Cool, Cool), and then (Cool, Real) and (Real, Cool)
  153. # candidates, but since Int both conforms to Cool and Real, we'd get lots
  154. # of ambiguous dispatches. So just go with (Any, Any) for now.
  155. multi sub atan2( \a, \b = 1e0) { a.Numeric.atan2(b.Numeric) }
  156. proto sub unpolar($, $) {*}
  157. multi sub unpolar(Real $mag, Real $angle) { $mag.unpolar($angle) }