Skip to content

Commit 87c25b7

Browse files
committed
jcomplex
1 parent 9f2bea7 commit 87c25b7

File tree

2 files changed

+253
-0
lines changed

2 files changed

+253
-0
lines changed

library/jcomplex/jcomplex.rb

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
java_import Java::MonkstoneComplex::JComplex
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
package monkstone.complex;
2+
3+
import java.util.Objects;
4+
5+
/**
6+
* The purpose of this class is to to make Complex operations more efficient
7+
* than JRuby RubyComplex, by having a simpler interface, only modest
8+
* improvements were obtained (but this is better than nothing on RaspberryPI).
9+
*/
10+
public final class JComplex {
11+
12+
private final double re; // the real part
13+
private final double im; // the imaginary part
14+
private final static JComplex ZERO = new JComplex(0, 0);
15+
private final static JComplex NAN = new JComplex(Double.NaN, Double.NaN);
16+
17+
/**
18+
* create a new object with the given real and imaginary parts
19+
*
20+
* @param real
21+
* @param imag
22+
*/
23+
public JComplex(double real, double imag) {
24+
re = real;
25+
im = imag;
26+
}
27+
28+
/**
29+
* @return a string representation of the invoking Complex object
30+
*/
31+
@Override
32+
public String toString() {
33+
return "JComplex(" + re + ", " + im + "i)";
34+
}
35+
36+
/**
37+
*
38+
* @return abs/modulus/magnitude
39+
*/
40+
public final double abs() {
41+
return Math.hypot(re, im);
42+
}
43+
44+
/**
45+
*
46+
* @return square of abs/modulus/magnitude
47+
*/
48+
public final double abs2() {
49+
return re * re + im * im;
50+
}
51+
52+
/**
53+
*
54+
* @return angle/phase/argument, normalized to be between -pi and pi
55+
*/
56+
public final double phase() {
57+
return Math.atan2(im, re);
58+
}
59+
60+
/**
61+
*
62+
* @param b
63+
* @return a new Complex object whose value is (this + b)
64+
*/
65+
public final JComplex add(JComplex b) {
66+
JComplex a = this; // invoking object
67+
double real = a.re + b.re;
68+
double imag = a.im + b.im;
69+
return new JComplex(real, imag);
70+
}
71+
72+
/**
73+
*
74+
* @param scalar
75+
* @return a new Complex object whose value is (this + scalar)
76+
*/
77+
public final JComplex add(double scalar) {
78+
return new JComplex(re + scalar, im);
79+
}
80+
81+
public final boolean zero() {
82+
return this.equals(ZERO);
83+
}
84+
85+
/**
86+
*
87+
* @param b
88+
* @return a new Complex object whose value is (this - b)
89+
*/
90+
public final JComplex sub(JComplex b) {
91+
JComplex a = this;
92+
double real = a.re - b.re;
93+
double imag = a.im - b.im;
94+
return new JComplex(real, imag);
95+
}
96+
97+
/**
98+
*
99+
* @param scalar
100+
* @return a new Complex object whose value is (this - scalar)
101+
*/
102+
public final JComplex sub(double scalar) {
103+
return new JComplex(re - scalar, im);
104+
}
105+
106+
/**
107+
*
108+
* @param b
109+
* @return a new Complex object whose value is (this * b)
110+
*/
111+
public final JComplex mul(JComplex b) {
112+
JComplex a = this;
113+
double real = a.re * b.re - a.im * b.im;
114+
double imag = a.re * b.im + a.im * b.re;
115+
return new JComplex(real, imag);
116+
}
117+
118+
/**
119+
* Also known as scale
120+
*
121+
* @param b
122+
* @return a new Complex object whose value is (this * b)
123+
*/
124+
public final JComplex mul(double b) {
125+
return new JComplex(re * b, im * b);
126+
}
127+
128+
/**
129+
*
130+
* @return a new Complex object whose value is the conjugate of this
131+
*/
132+
public final JComplex conjugate() {
133+
return new JComplex(re, -im);
134+
}
135+
136+
/**
137+
*
138+
* @return a new Complex object whose value is the reciprocal of this
139+
*/
140+
private JComplex reciprocal() {
141+
double scale = re * re + im * im; // self dot product
142+
return new JComplex(re / scale, -im / scale);
143+
}
144+
145+
/**
146+
*
147+
* @param other
148+
* @return this^other
149+
*/
150+
public final JComplex pow(JComplex other) {
151+
if (this.zero()) {
152+
if (other.zero()) {
153+
return ZERO;
154+
}
155+
return NAN;
156+
}
157+
return (this).log().mul(other).exp();
158+
}
159+
160+
/**
161+
*
162+
* @param scalar
163+
* @return this^scalar
164+
*/
165+
public final JComplex pow(double scalar) {
166+
if (this.zero()) {
167+
if (scalar == 0) {
168+
return ZERO;
169+
}
170+
return NAN;
171+
}
172+
return (this).log().mul(scalar).exp();
173+
}
174+
175+
/**
176+
*
177+
* @return log
178+
*/
179+
private JComplex log() {
180+
return new JComplex(Math.log(abs()), Math.atan2(im, re));
181+
}
182+
183+
/**
184+
*
185+
* @return real part
186+
*/
187+
public final double re() {
188+
return re;
189+
}
190+
191+
/**
192+
*
193+
* @return imaginary part
194+
*/
195+
public final double im() {
196+
return im;
197+
}
198+
199+
/**
200+
*
201+
* @param b
202+
* @return a / b
203+
*/
204+
public final JComplex div(JComplex b) {
205+
JComplex a = this;
206+
return a.mul(b.reciprocal());
207+
}
208+
209+
/**
210+
*
211+
* @param b
212+
* @return a / b
213+
*/
214+
public final JComplex div(double b) {
215+
if (b == 0) {
216+
return NAN;
217+
}
218+
return new JComplex(re / b, im / b);
219+
}
220+
221+
/**
222+
*
223+
* @return a new Complex object whose value is the complex exponential of
224+
* this
225+
*/
226+
public final JComplex exp() {
227+
return new JComplex(Math.exp(re) * Math.cos(im), Math.exp(re) * Math.sin(im));
228+
}
229+
230+
@Override
231+
public final int hashCode() {
232+
return Objects.hash(re, im);
233+
}
234+
235+
@Override
236+
public final boolean equals(Object obj) {
237+
if (this == obj) {
238+
return true;
239+
}
240+
if (obj == null) {
241+
return false;
242+
}
243+
if (getClass() != obj.getClass()) {
244+
return false;
245+
}
246+
final JComplex other = (JComplex) obj;
247+
if (Double.doubleToLongBits(this.re) != Double.doubleToLongBits(other.re)) {
248+
return false;
249+
}
250+
return Double.doubleToLongBits(this.im) == Double.doubleToLongBits(other.im);
251+
}
252+
}

0 commit comments

Comments
 (0)