RosettaCodeData/Task/Arithmetic-Complex/Groovy/arithmetic-complex-1.groovy

101 lines
3.9 KiB
Groovy
Raw Permalink Normal View History

2013-04-10 21:29:02 -07:00
class Complex {
final Number real, imag
2015-02-20 00:35:01 -05:00
static final Complex i = [0,1] as Complex
2013-04-10 21:29:02 -07:00
2015-02-20 00:35:01 -05:00
Complex(Number r, Number i = 0) { (real, imag) = [r, i] }
2013-04-10 21:29:02 -07:00
2015-02-20 00:35:01 -05:00
Complex(Map that) { (real, imag) = [that.real ?: 0, that.imag ?: 0] }
2013-04-10 21:29:02 -07:00
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 }
2015-02-20 00:35:01 -05:00
/** the complex conjugate of this complex number. Overloads the bitwise complement (~) operator. */
2013-04-10 21:29:02 -07:00
Complex bitwiseNegate () { [real, -imag] as Complex }
/** the magnitude of this complex number. */
2015-02-20 00:35:01 -05:00
// could also use Math.sqrt( (this * (~this)).real )
Number getAbs() { Math.sqrt( real*real + imag*imag ) }
/** the magnitude of this complex number. */
Number abs() { this.abs }
2013-04-10 21:29:02 -07:00
2015-02-20 00:35:01 -05:00
/** the reciprocal of this complex number. */
Complex getRecip() { (~this) / (ρ**2) }
/** the reciprocal of this complex number. */
Complex recip() { this.recip }
2013-04-10 21:29:02 -07:00
2015-02-20 00:35:01 -05:00
/** derived polar angle θ (theta) for polar form. Normalized to 0 ≤ θ < 2π. */
2013-04-10 21:29:02 -07:00
Number getTheta() {
2015-02-20 00:35:01 -05:00
def θ = Math.atan2(imag,real)
θ = θ < 0 ? θ + 2 * Math.PI : θ
2013-04-10 21:29:02 -07:00
}
2015-02-20 00:35:01 -05:00
/** derived polar angle θ (theta) for polar form. Normalized to 0 ≤ θ < 2π. */
Number getΘ() { this.theta } // this is greek uppercase theta
2013-04-10 21:29:02 -07:00
2015-02-20 00:35:01 -05:00
/** derived polar magnitude ρ (rho) for polar form. */
Number getRho() { this.abs }
/** derived polar magnitude ρ (rho) for polar form. */
Number getΡ() { this.abs } // this is greek uppercase rho, not roman P
2013-04-10 21:29:02 -07:00
/** Runs Euler's polar-to-Cartesian complex conversion,
2015-02-20 00:35:01 -05:00
* converting [ρ, θ] inputs into a [real, imag]-based complex number */
static Complex fromPolar(Number ρ, Number θ) {
[ρ * Math.cos(θ), ρ * Math.sin(θ)] as Complex
2013-04-10 21:29:02 -07:00
}
2015-02-20 00:35:01 -05:00
/** Creates new complex with same magnitude ρ, but different angle θ */
Complex withTheta(Number θ) { fromPolar(this.rho, θ) }
/** Creates new complex with same magnitude ρ, but different angle θ */
Complex withΘ(Number θ) { fromPolar(this.rho, θ) }
2013-04-10 21:29:02 -07:00
2015-02-20 00:35:01 -05:00
/** Creates new complex with same angle θ, but different magnitude ρ */
Complex withRho(Number ρ) { fromPolar(ρ, this.θ) }
/** Creates new complex with same angle θ, but different magnitude ρ */
Complex withΡ(Number ρ) { fromPolar(ρ, this.θ) } // this is greek uppercase rho, not roman P
2013-04-10 21:29:02 -07:00
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) }
2015-02-20 00:35:01 -05:00
boolean equals(that) {
that != null && (that instanceof Complex \
? [this.real, this.imag] == [that.real, that.imag] \
: that instanceof Number && [this.real, this.imag] == [that, 0])
2013-04-10 21:29:02 -07:00
}
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
}
}