package ti.lang; import java.util.StringTokenizer; // Complex number immutable class (polar) // Kaushik Datta and Dan Bonachea {kdatta,bonachea}@cs.berkeley.edu public immutable class ComplexPolar { public double r; // magnitude (always >= 0, or NaN) public double theta; // angle in radians, where -pi < theta <= pi private static final double NaN = Double.NaN; private static final double pi = Math.PI; public inline ComplexPolar() { r = 0.0; theta = 0.0; } /* This constructor puts the complex number in standard polar form */ public ComplexPolar(double paramR, double paramTheta) { if (Double.isNaN(paramR+paramTheta)) { r = NaN; theta = 0.0; } else { if (paramR >= 0) { r = paramR; } else { r = -paramR; paramTheta += pi; } theta = paramTheta + 2 * pi * Math.floor((pi - paramTheta)/(2 * pi)); } } public String toString() { String s = new String(""); if (r == 0) { s = "0.0"; } else { s = s + r + " * e^(" + theta + "i)"; } return s; } /* String s must be in the form r or r * e^(ti), where r and t can be parsed into doubles */ public static ComplexPolar parseComplexPolar(String s) throws NullPointerException, NumberFormatException { String token1, token2; double magnitude = 0.0; double angle = 0.0; StringTokenizer st = new StringTokenizer(s, "*e^() ", false); if (st.hasMoreTokens()) { token1 = st.nextToken(); } else { throw new NumberFormatException(); } magnitude = Double.valueOf(token1).doubleValue(); if (st.hasMoreTokens()) { token2 = st.nextToken(); if (token2.endsWith("i")) { angle = Double.valueOf(token2.substring(0, token2.length()-2)).doubleValue(); } else { throw new NumberFormatException(); } } if (st.hasMoreTokens()) { throw new NumberFormatException(); } else { return new ComplexPolar(magnitude, angle); } } public inline ComplexPolar op-() { return new ComplexPolar(r, theta + pi); } public inline ComplexPolar op+(double d1) { return (this.toRect() + d1).toPolar(); } public inline ComplexPolar op+(ComplexPolar cp1) { return (this.toRect() + cp1.toRect()).toPolar(); } public inline ComplexPolar op-(double d1) { return (this.toRect() - d1).toPolar(); } public inline ComplexPolar op-(ComplexPolar cp1) { return (this.toRect() - cp1.toRect()).toPolar(); } public inline ComplexPolar op*(double d1) { return new ComplexPolar(r * d1, theta); } public inline ComplexPolar op*(ComplexPolar cp1) { return new ComplexPolar(r * cp1.r, theta + cp1.theta); } public inline ComplexPolar op/(double d1) { return new ComplexPolar(r / d1, theta); } public inline ComplexPolar op/(ComplexPolar cp1) { return new ComplexPolar(r / cp1.r, theta - cp1.theta); } public inline boolean op==(double d1) { if (d1 > 0.0) { return ((r == d1) && (theta == 0.0)); } else if (d1 < 0.0) { return ((r == -d1) && (theta == pi)); } else { return (r == 0.0); } } public inline boolean op==(ComplexPolar cp1) { if (r > 0.0) { return ((r == cp1.r) && (theta == cp1.theta)); } else { return (cp1.r == 0); } } public inline boolean op!=(double d1) { if (d1 > 0) { return ((r != d1) || (theta != 0.0)); } else if (d1 < 0) { return ((r != -d1) || (theta != pi)); } else { return (r != 0.0); } } public inline boolean op!=(ComplexPolar cp1) { if (r > 0.0) { return ((r != cp1.r) || (theta != cp1.theta)); } else { return (cp1.r != 0.0); } } // complex conjugate public inline ComplexPolar op~() { return new ComplexPolar(r, -theta); } // complex number raised to double power public inline ComplexPolar op^(double d1) { if (r > 0.0) { return new ComplexPolar(Math.pow(r, d1), theta * d1); } else { if (d1 != 0.0) { return this; } else { return new ComplexPolar(NaN, 0.0); } } } // complex number raised to complex power public inline ComplexPolar op^(ComplexPolar cp1) { if (r > 0.0) { return (cp1 * log()).exp(); } else { if (cp1.r > 0.0) { return this; } else { return new ComplexPolar(NaN, 0.0); } } } /* non-operator overloading methods */ public inline ComplexPolar neg() { return (-this); } public inline ComplexPolar add(double d1) { return (this + d1); } public inline ComplexPolar add(ComplexPolar cp1) { return (this + cp1); } public static inline ComplexPolar add(ComplexPolar cp1, double d1) { return (cp1 + d1); } /* this add is for (d1 + cp1), which is undefined using operator overloading */ public static inline ComplexPolar add(double d1, ComplexPolar cp1) { return (cp1 + d1); } public inline ComplexPolar sub(double d1) { return (this - d1); } public inline ComplexPolar sub(ComplexPolar cp1) { return (this - cp1); } public static inline ComplexPolar sub(ComplexPolar cp1, double d1) { return (cp1 - d1); } /* this subtract is for (d1 - cp1), which is undefined using operator overloading */ public static inline ComplexPolar sub(double d1, ComplexPolar cp1) { return Complex.sub(d1, cp1.toRect()).toPolar(); } public inline ComplexPolar mult(double d1) { return (this * d1); } public inline ComplexPolar mult(ComplexPolar cp1) { return (this * cp1); } public static inline ComplexPolar mult(ComplexPolar cp1, double d1) { return (cp1 * d1); } /* this multiply is for (d1 * cp1), which is undefined using operator overloading */ public static inline ComplexPolar mult(double d1, ComplexPolar cp1) { return (cp1 * d1); } public inline ComplexPolar div(double d1) { return (this / d1); } public inline ComplexPolar div(ComplexPolar cp1) { return (this / cp1); } public static inline ComplexPolar div(ComplexPolar cp1, double d1) { return (cp1 / d1); } /* this divide is for (d1 / cp1), which is undefined using operator overloading */ public static inline ComplexPolar div(double d1, ComplexPolar cp1) { return Complex.div(d1, cp1.toRect()).toPolar(); } public inline boolean eq(double d1) { return (this == d1); } public inline boolean eq(ComplexPolar cp1) { return (this == cp1); } public inline boolean neq(double d1) { return (this != d1); } public inline boolean neq(ComplexPolar cp1) { return (this != cp1); } public inline ComplexPolar conj() { return ~this; } public inline ComplexPolar pow(double d1) { return this^d1; } public inline ComplexPolar pow(ComplexPolar cp1) { return this^cp1; } public inline ComplexPolar exp() { return new ComplexPolar(Math.exp(re()), im()); } public inline ComplexPolar log() { return (new Complex(Math.log(r), theta)).toPolar(); } public inline ComplexPolar sqrt() { return new ComplexPolar(Math.sqrt(r), theta/2.0); } public ComplexPolar sin() { return this.toRect().sin().toPolar(); } public ComplexPolar cos() { return this.toRect().cos().toPolar(); } public ComplexPolar tan() { return this.toRect().tan().toPolar(); } public ComplexPolar asin() { return this.toRect().asin().toPolar(); } public ComplexPolar acos() { return this.toRect().acos().toPolar(); } public ComplexPolar atan() { return this.toRect().atan().toPolar(); } public ComplexPolar sinh() { return this.toRect().sinh().toPolar(); } public ComplexPolar cosh() { return this.toRect().cosh().toPolar(); } public ComplexPolar tanh() { return this.toRect().tanh().toPolar(); } public ComplexPolar asinh() { return this.toRect().asinh().toPolar(); } public ComplexPolar acosh() { return this.toRect().acosh().toPolar(); } public ComplexPolar atanh() { return this.toRect().atanh().toPolar(); } /* Methods for converting to rectangular */ // returns real component of ComplexPolar public inline double re() { return (r * Math.cos(theta)); } // returns imaginary component of ComplexPolar public inline double im() { return (r * Math.sin(theta)); } // converts ComplexPolar to Complex public inline Complex toRect() { return new Complex(re(), im()); } }