You need Integral
rather than Numeric
if you want Complex
with method /
.
Here is an almost completed solution:
scala> :paste
// Entering paste mode (ctrl-D to finish)
import scala.math.Integral
class Complex[T: Integral](val real: T, val imag: T) {
import Integral.Implicits._
def +(that: Complex[T]) = Complex(real+that.real, imag+that.imag)
def -(that: Complex[T]) = Complex(real-that.real, imag-that.imag)
def *(that: Complex[T]) = Complex(real*that.real - imag*that.imag, real*that.imag+imag*that.real)
def /(that: Complex[T]) = {
val d = that.real*that.real + that.imag*that.imag
Complex((real*that.real + imag*that.imag)/d, (-real*that.imag+imag*that.real)/d)
}
override def toString: String = imag.signum match {
case 1 => "" + real + "+" + imag +"i"
case -1 => "" + real + "" + imag + "i"
case _ => "" + real
}
}
object Complex {
import Integral.Implicits._
def apply[T: Integral](real: T, imag: T): Complex[T] = new Complex[T](real, imag)
object i extends Complex[Byte](0.toByte, 1.toByte)
implicit class Real2Imag[T](val imag: T) {
def *(v: i.type)(implicit ig: Integral[T]) = Complex(ig.zero, imag)
}
implicit def promote[U, V](c: Complex[U])(implicit ev: U => V, il: Integral[V]) =
Complex(ev(c.real), ev(c.imag))
implicit def real2complex[T: Integral](real: T) = Complex(real, implicitly[Integral[T]].zero)
implicit val doubleIsIntegral = scala.math.Numeric.DoubleAsIfIntegral
}
// Exiting paste mode, now interpreting.
warning: there were 2 feature warnings; re-run with -feature for details
import scala.math.Integral
defined class Complex
defined object Complex
scala> import Complex._
import Complex._
scala> val c1 = 3 + 4*i
c1: Complex[Int] = 3+4i
scala> val c2 = 3.0 + 4.0*i
c2: Complex[Double] = 3.0+4.0i
scala> val c3 = c1/c2
c3: Complex[Double] = 1.0
scala> val c4 = 3 - 4*i
c4: Complex[Int] = 3-4i
scala> val c5 = c2*c4
c5: Complex[Double] = 25.0
You can write your pow
method as this (Note how to generate a Complex
one):
def pow(n: Int): Complex[T] = {
val one = Complex[T](implicitly[Integral[T]].one, implicitly[Integral[T]].zero)
Iterator.iterate(one)(_*this).drop(n).next
}
scala> i.pow(2)
res5: Complex[Byte] = -1
scala> i.pow(10)
res6: Complex[Byte] = -1
scala> (1+1*i).pow(4)
res7: Complex[Int] = -4
scala> (1+1*i).pow(5)
res8: Complex[Int] = -4-4i
Double
, or is Complex`` parametric? From the code snippet I gather it is not parametric (and so it probably types as Double so as to be able to accomodate all the input types), but I'd like a confirmation. – Régis Jean-Gilles