atan2 function is defined as follows:
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:
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:
After reading up a little more on scala extractors, I could come up with a crazier version of the same:
However, this unfortunately requires defining 5 extractors this way:
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
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