I wanted to try a small exercise of implementing this using scala(ignoring the fact that it is already natively implemented in java.lang.Math library).
The simplest implementation that I could think of is with a if expression this way:
def atan2(x: Double, y: Double):Double = { if (x >0) atan(y/x) else if (y >= 0 && x < 0) Pi + atan(y/x) else if (y < 0 && x < 0) atan(y/x) - Pi else if (y > 0 && x==0) Pi/2 else if (y < 0 && x==0) -Pi/2 else Double.NaN }
However, I wanted to see at this point if it could be reimplemented using a case-match expression, and I could only come up with a souped up version of if/else this way:
def atan2(x: Double, y: Double): Double = { true match { case _ if (x>0) => atan(y/x) case _ if (y >= 0 && x < 0) => atan(y/x) + Pi case _ if (y < 0 && x < 0) => atan(y/x) - Pi case _ if (y > 0 && x==0) => Pi/2 case _ if (y <0 && x==0) => -Pi/2 case _ => Double.NaN } }
After reading up a little more on scala extractors, I could come up with a crazier version of the same:
def atan2(x: Double, y: Double): Double = { (x, y) match { case xgt0() => atan(y/x) case ygte0Andxlt0() => atan(y/x) + Pi case ylt0Andxlt0() => atan(y/x) - Pi case ygt0Andxeq0() => Pi/2 case ylt0Andxeq0() => -Pi/2 case _ => Double.NaN } }
However, this unfortunately requires defining 5 extractors this way:
object xgt0 { def unapply(tup: (Double, Double)): Boolean = tup match { case (x,y) => (x>0)} } object ygte0Andxlt0 { def unapply(tup: (Double, Double)): Boolean = tup match { case (x, y) => (y >= 0 && x < 0)} } object ylt0Andxlt0 { def unapply(tup: (Double, Double)): Boolean = tup match { case (x, y) => (y < 0 && x < 0)} } object ygt0Andxeq0 { def unapply(tup: (Double, Double)): Boolean = tup match { case (x, y) => (y > 0 && x == 0)} } object ylt0Andxeq0 { def unapply(tup: (Double, Double)): Boolean = tup match { case (x, y) => (y < 0 && x == 0)} }
The only conclusion I could make out of this is that if I had to re-write atan2 in scala the best approach is probably using the first one - using if expression. I am sure there is definitely a more scala way of doing this and would definitely appreciate any suggestions on these approaches
No comments:
Post a Comment