Created
March 24, 2012 15:59
-
-
Save non/2184595 to your computer and use it in GitHub Desktop.
using SIP-15 value classes to encode complex numbers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import scala.math._ | |
object Main { | |
def main(args:Array[String]) { | |
val a = LongComplex(13, 0) | |
val b = LongComplex(6, 2) | |
//println(a) | |
//println(b) | |
val c = a + b | |
//println(c) | |
//println(a - b) | |
//println(a * b) | |
//println(a / b) | |
println(if (c == LongComplex.zero) "zero" else "not-zero") | |
} | |
} | |
object LongComplex { | |
@inline final def f2i(n:Float):Int = java.lang.Float.floatToRawIntBits(n) | |
@inline final def i2f(n:Int):Float = java.lang.Float.intBitsToFloat(n) | |
final val i = LongComplex(0.0F, 1.0F) | |
final val one = LongComplex(1.0F, 0.0F) | |
final val zero = LongComplex(0.0F, 0.0F) | |
def apply(real:Float, imag:Float) = { | |
val u = (f2i(imag).toLong << 32) + f2i(real).toLong | |
new LongComplex(u) | |
} | |
def polar(magnitude:Float, angle:Float) = { | |
apply(magnitude * cos(angle).toFloat, magnitude * sin(angle).toFloat) | |
} | |
} | |
class LongComplex(val u:Long) extends AnyVal { | |
def real = LongComplex.i2f((u & 0xffffffff).toInt) | |
def imag = LongComplex.i2f((u >> 32).toInt) | |
override def toString = "LongComplex(%s, %s)" format (real, imag) | |
def unary_- = LongComplex(-real, -imag) | |
def +(rhs:LongComplex) = LongComplex(real + rhs.real, imag + rhs.imag) | |
def -(rhs:LongComplex) = LongComplex(real - rhs.real, imag - rhs.imag) | |
def *(rhs:LongComplex) = { | |
val re1 = real | |
val im1 = imag | |
val re2 = rhs.real | |
val im2 = rhs.imag | |
LongComplex(re1 * re2 - im1 * im2, im1 * re2 + re1 * im2) | |
} | |
def /(rhs:LongComplex) = { | |
val re1 = real | |
val im1 = imag | |
val re2 = rhs.real | |
val im2 = rhs.imag | |
val abs_re2 = math.abs(re2) | |
val abs_im2 = math.abs(im2) | |
if (abs_re2 >= abs_im2) { | |
if (abs_re2 == 0.0F) sys.error("/0") | |
val ratio = im2 / re2 | |
val denom = re2 + im2 * ratio | |
LongComplex((re1 + im1 * ratio) / denom, (im1 - re1 * ratio) / denom) | |
} else { | |
if (abs_im2 == 0.0F) sys.error("/0") | |
val ratio = re2 / im2 | |
val denom = re2 * ratio + im2 | |
LongComplex((re1 * ratio + im1) / denom, (im1 * ratio - re1) / denom) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment