This commit is contained in:
Ingy döt Net 2013-04-10 21:29:02 -07:00
parent 764da6cbbb
commit db842d013d
19005 changed files with 197040 additions and 7 deletions

View file

@ -0,0 +1,94 @@
class Complex {
final Number real, imag
static final Complex I = [0,1] as Complex
Complex(Number real) { this(real, 0) }
Complex(real, imag) { this.real = real; this.imag = imag }
Complex plus (Complex c) { [real + c.real, imag + c.imag] as Complex }
Complex plus (Number n) { [real + n, imag] as Complex }
Complex minus (Complex c) { [real - c.real, imag - c.imag] as Complex }
Complex minus (Number n) { [real - n, imag] as Complex }
Complex multiply (Complex c) { [real*c.real - imag*c.imag , imag*c.real + real*c.imag] as Complex }
Complex multiply (Number n) { [real*n , imag*n] as Complex }
Complex div (Complex c) { this * c.recip() }
Complex div (Number n) { this * (1/n) }
Complex negative () { [-real, -imag] as Complex }
/** the complex conjugate of this complex number.
* Overloads the bitwise complement (~) operator. */
Complex bitwiseNegate () { [real, -imag] as Complex }
/** the magnitude of this complex number. */
// could also use Math.sqrt( (this * (~this)).real )
Number abs () { Math.sqrt( real*real + imag*imag ) }
/** the complex reciprocal of this complex number. */
Complex recip() { (~this) / ((this * (~this)).real) }
/** derived angle θ (theta) for polar form.
* Normalized to 0 &#x2264; &#x03B8; < 2&#x03C0;. */
Number getTheta() {
def theta = Math.atan2(imag,real)
theta = theta < 0 ? theta + 2 * Math.PI : theta
}
/** derived magnitude &#x03C1; (rho) for polar form. */
Number getRho() { this.abs() }
/** Runs Euler's polar-to-Cartesian complex conversion,
* converting [&#x03C1;, &#x03B8;] inputs into a [real, imag]-based complex number */
static Complex fromPolar(Number rho, Number theta) {
[rho * Math.cos(theta), rho * Math.sin(theta)] as Complex
}
/** Creates new complex with same magnitude &#x03C1;, but different angle &#x03B8; */
Complex withTheta(Number theta) { fromPolar(this.rho, theta) }
/** Creates new complex with same angle &#x03B8;, but different magnitude &#x03C1; */
Complex withRho(Number rho) { fromPolar(rho, this.theta) }
static Complex exp(Complex c) { fromPolar(Math.exp(c.real), c.imag) }
static Complex log(Complex c) { [Math.log(c.rho), c.theta] as Complex }
Complex power(Complex c) {
this == 0 && c != 0 \
? [0] as Complex \
: c == 1 \
? this \
: exp( log(this) * c )
}
Complex power(Number n) { this ** ([n, 0] as Complex) }
boolean equals(other) {
other != null && (other instanceof Complex \
? [real, imag] == [other.real, other.imag] \
: other instanceof Number && [real, imag] == [other, 0])
}
int hashCode() { [real, imag].hashCode() }
String toString() {
def realPart = "${real}"
def imagPart = imag.abs() == 1 ? "i" : "${imag.abs()}i"
real == 0 && imag == 0 \
? "0" \
: real == 0 \
? (imag > 0 ? '' : "-") + imagPart \
: imag == 0 \
? realPart \
: realPart + (imag > 0 ? " + " : " - ") + imagPart
}
}

View file

@ -0,0 +1,36 @@
def tol = 0.000000001 // tolerance: acceptable "wrongness" to account for rounding error
println 'Demo 1: functionality as requested'
def a = [5,3] as Complex
println 'a == ' + a
def b = [0.5,6] as Complex
println 'b == ' + b
println "a + b == (${a}) + (${b}) == " + (a + b)
println "a * b == (${a}) * (${b}) == " + (a * b)
assert a + (-a) == 0
println "-a == -(${a}) == " + (-a)
assert (a * a.recip() - 1).abs() < tol
println "1/a == (${a}).recip() == " + (a.recip())
println()
println 'Demo 2: other functionality not requested, but important for completeness'
println "a - b == (${a}) - (${b}) == " + (a - b)
println "a / b == (${a}) / (${b}) == " + (a / b)
println "a ** b == (${a}) ** (${b}) == " + (a ** b)
println 'a.real == ' + a.real
println 'a.imag == ' + a.imag
println 'a.rho == ' + a.rho
println 'a.theta == ' + a.theta
println '|a| == ' + a.abs()
println 'a_bar == ' + ~a
def rho = 10
def piOverTheta = 3
def theta = Math.PI / piOverTheta
def fromPolar1 = Complex.fromPolar(rho, theta) // direct polar-to-cartesian conversion
def fromPolar2 = Complex.exp(Complex.I * theta) * rho // Euler's equation
println "rho*cos(theta) + rho*i*sin(theta) == ${rho}*cos(pi/${piOverTheta}) + ${rho}*i*sin(pi/${piOverTheta}) == " + fromPolar1
println "rho * exp(i * theta) == ${rho} * exp(i * pi/${piOverTheta}) == " + fromPolar2
assert (fromPolar1 - fromPolar2).abs() < tol
println()