1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// 複素数(お題:http://ja.doukaku.org/247/)
// http://ja.doukaku.org/comment/----/
// snaさん作を改変( : http://ja.doukaku.org/comment/8851/)
// 参考 : http://en.literateprograms.org/Complex_numbers_(Scala)

trait Arithmetic[T<:AnyVal]{
  def unary_+ : T
  def unary_- : T
  def + (that:T):T
  def - (that:T):T
  def * (that:T):T
  def / (that:T):T
  def abs : T
  //
  def lt0 : Boolean  // >   0
  def gt0 : Boolean  // <   0
  def eq0 : Boolean  // ==  0
  //
  def eqp1 : Boolean // ==  1
  def eqm1 : Boolean // == -1
  //
}

case class Complex[ T<%Arithmetic[T] ](real:T, imag:T) {
  // +(a + bi) = (a + bi)
  def unary_+ = this
  
  // -(a + bi) = (-a - bi)
  def unary_- = Complex[T](-real, -imag)
  
  // (a + bi) + (c + di) = (a + c) + (b + d)i
  def + (that: Complex[T]) = Complex(this.real + that.real, this.imag + that.imag)
  
  // (a + bi) - (c + di) = (a - c) + (b - d)i
  def - (that: Complex[T]) = Complex(this.real - that.real, this.imag - that.imag)
  
  // (a + bi) * (c + di) = (ac - bd) + (bc + ad)i
  def * (that: Complex[T]) = {
    val Complex(a, b) = this
    val Complex(c, d) = that
    Complex(a*c - b*d, b*c + a*d)
  }
  
  // (a + bi) / (c + di) = (ac + bd) / (c^2 + d^2) + (bc - ad) / (c^2 + d^2)
  def / (that: Complex[T]) = {
    val Complex(a, b) = this
    val Complex(c, d) = that
    val deno = c*c + d*d
    Complex((a*c + b*d) / deno, (b*c - a*d) / deno)
  }
  
  // Conjugate
  def conjugate() : Complex[T] = Complex(real,-imag)
  
  override def toString = this match {
    case Complex(re, im) if im.eq0            => re.toString
    case Complex(re, im) if re.eq0 && im.eqp1 => "i"
    case Complex(re, im) if re.eq0 && im.eqm1 => "-i"
    case Complex(re, im) if re.eq0            => im.toString + "i"
    case Complex(re, im) if           im.eqp1 => re.toString + " + i"
    case Complex(re, im) if           im.eqm1 => re.toString + " - i"
    case Complex(re, im) if           im.gt0  => re.toString + " + " + im.toString + "i"
    case Complex(re, im) if           im.lt0  => re.toString + " - " + im.abs.toString + "i"
  }

}

object test{
  implicit def int2Arithmeic(n:Int) : Arithmetic[Int] = 
                    new Arithmetic[Int]{
                         def unary_+ : Int  = n.unary_+
                         def unary_- : Int  = n.unary_-
                         def + (that:Int):Int = n+that
                         def - (that:Int):Int = n-that
                         def * (that:Int):Int = n*that
                         def / (that:Int):Int = n/that
                         def abs = Math.abs(n)
                         //
                         def lt0 = n<0
                         def gt0 = n>0
                         def eq0 = n==0
                         //
                         def eqp1 = n==1 
                         def eqm1 = n== -1  }
  
  implicit def double2Arithmeic(n:Double) : Arithmetic[Double] = 
                    new Arithmetic[Double]{
                         def unary_+ : Double  = n.unary_+
                         def unary_- : Double  = n.unary_-
                         def + (that:Double):Double = n+that
                         def - (that:Double):Double = n-that
                         def * (that:Double):Double = n*that
                         def / (that:Double):Double = n/that
                         def abs = Math.abs(n)
                         //
                         def lt0 = n<0
                         def gt0 = n>0
                         def eq0 = n==0
                         //
                         def eqp1 = n==1 
                         def eqm1 = n== -1  }
  
  implicit def int2Complex   (n:Int   ):Complex[Int   ] = Complex(n,0)
  implicit def double2Complex(n:Double):Complex[Double] = Complex(n,0)
  implicit def icomp2dcomp   (z:Complex[Int]):Complex[Double] = Complex(z.real,z.imag)
  
  implicit def dcomp2richer  (z:Complex[Double]) = new Proxy{
       val self=z
       def abs = self match {
         case Complex(re, im) => Math.sqrt(re*re + im*im)
       }
    }
  
  implicit def icomp2richer  (z:Complex[int]) = new Proxy{
       val self=z
       def abs = self match {
         case Complex(re, im) => Math.sqrt(re*re + im*im)
       }
    }
  
  
  def main( args:Array[String] ) : Unit = {
    {
      val i = Complex(0,1)
      println( (3 + i  ) + (4 - i  ) )
      println( (5 - 9*i) - (2 + 6*i) )
      println( (5 + 3*i) * (5 + 8*i) )
      println( (9 - 7*i) / (9 - 3*i) )
      println( (2 + 3*i).abs         )
    }
    
    {
      val i = Complex(0.,1.)
      println( (3. + i  ) + (4. - i  ) )
      println( (5. - 9.*i) - (2. + 6.*i) )
      println( (5. + 3.*i) * (5. + 8.*i) )
      println( (9. - 7.*i) / (9. - 3.*i) )
      println( (2. + 3.*i).abs         )
    }
  }
}