1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.math.complex;
18
19 import java.io.Serializable;
20 import java.text.FieldPosition;
21 import java.text.Format;
22 import java.text.NumberFormat;
23 import java.text.ParseException;
24 import java.text.ParsePosition;
25 import java.util.Locale;
26
27
28
29
30
31
32
33
34
35 public class ComplexFormat extends Format implements Serializable {
36
37
38 private static final long serialVersionUID = -6337346779577272306L;
39
40
41 private static final String DEFAULT_IMAGINARY_CHARACTER = "i";
42
43
44 private String imaginaryCharacter;
45
46
47 private NumberFormat imaginaryFormat;
48
49
50 private NumberFormat realFormat;
51
52
53
54
55
56 public ComplexFormat() {
57 this(DEFAULT_IMAGINARY_CHARACTER, getDefaultNumberFormat());
58 }
59
60
61
62
63
64
65 public ComplexFormat(NumberFormat format) {
66 this(DEFAULT_IMAGINARY_CHARACTER, format);
67 }
68
69
70
71
72
73
74
75 public ComplexFormat(NumberFormat realFormat,
76 NumberFormat imaginaryFormat) {
77 this(DEFAULT_IMAGINARY_CHARACTER, realFormat, imaginaryFormat);
78 }
79
80
81
82
83
84
85 public ComplexFormat(String imaginaryCharacter) {
86 this(imaginaryCharacter, getDefaultNumberFormat());
87 }
88
89
90
91
92
93
94
95 public ComplexFormat(String imaginaryCharacter, NumberFormat format) {
96 this(imaginaryCharacter, format, (NumberFormat)format.clone());
97 }
98
99
100
101
102
103
104
105
106
107 public ComplexFormat(String imaginaryCharacter, NumberFormat realFormat,
108 NumberFormat imaginaryFormat) {
109 super();
110 setImaginaryCharacter(imaginaryCharacter);
111 setImaginaryFormat(imaginaryFormat);
112 setRealFormat(realFormat);
113 }
114
115
116
117
118
119
120
121
122 public static String formatComplex( Complex c ) {
123 return getInstance().format( c );
124 }
125
126
127
128
129
130
131
132
133
134
135 public StringBuffer format(Complex complex, StringBuffer toAppendTo,
136 FieldPosition pos) {
137
138 pos.setBeginIndex(0);
139 pos.setEndIndex(0);
140
141
142 double re = complex.getReal();
143 formatDouble(re, getRealFormat(), toAppendTo, pos);
144
145
146 double im = complex.getImaginary();
147 if (im < 0.0) {
148 toAppendTo.append(" - ");
149 formatDouble(-im, getImaginaryFormat(), toAppendTo, pos);
150 toAppendTo.append(getImaginaryCharacter());
151 } else if (im > 0.0 || Double.isNaN(im)) {
152 toAppendTo.append(" + ");
153 formatDouble(im, getImaginaryFormat(), toAppendTo, pos);
154 toAppendTo.append(getImaginaryCharacter());
155 }
156
157 return toAppendTo;
158 }
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173 public StringBuffer format(Object obj, StringBuffer toAppendTo,
174 FieldPosition pos) {
175
176 StringBuffer ret = null;
177
178 if (obj instanceof Complex) {
179 ret = format( (Complex)obj, toAppendTo, pos);
180 } else if (obj instanceof Number) {
181 ret = format( new Complex(((Number)obj).doubleValue(), 0.0),
182 toAppendTo, pos);
183 } else {
184 throw new IllegalArgumentException(
185 "Cannot format given Object as a Date");
186 }
187
188 return ret;
189 }
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208 private StringBuffer formatDouble(double value, NumberFormat format,
209 StringBuffer toAppendTo, FieldPosition pos) {
210 if( Double.isNaN(value) || Double.isInfinite(value) ) {
211 toAppendTo.append('(');
212 toAppendTo.append(value);
213 toAppendTo.append(')');
214 } else {
215 getRealFormat().format(value, toAppendTo, pos);
216 }
217 return toAppendTo;
218 }
219
220
221
222
223
224
225 public static Locale[] getAvailableLocales() {
226 return NumberFormat.getAvailableLocales();
227 }
228
229
230
231
232
233
234
235 private static NumberFormat getDefaultNumberFormat() {
236 return getDefaultNumberFormat(Locale.getDefault());
237 }
238
239
240
241
242
243
244
245
246 private static NumberFormat getDefaultNumberFormat(Locale locale) {
247 NumberFormat nf = NumberFormat.getInstance(locale);
248 nf.setMaximumFractionDigits(2);
249 return nf;
250 }
251
252
253
254
255
256 public String getImaginaryCharacter() {
257 return imaginaryCharacter;
258 }
259
260
261
262
263
264 public NumberFormat getImaginaryFormat() {
265 return imaginaryFormat;
266 }
267
268
269
270
271
272 public static ComplexFormat getInstance() {
273 return getInstance(Locale.getDefault());
274 }
275
276
277
278
279
280
281 public static ComplexFormat getInstance(Locale locale) {
282 NumberFormat f = getDefaultNumberFormat(locale);
283 return new ComplexFormat(f);
284 }
285
286
287
288
289
290 public NumberFormat getRealFormat() {
291 return realFormat;
292 }
293
294
295
296
297
298
299
300
301
302 public Complex parse(String source) throws ParseException {
303 ParsePosition parsePosition = new ParsePosition(0);
304 Complex result = parse(source, parsePosition);
305 if (parsePosition.getIndex() == 0) {
306 throw new ParseException("Unparseable complex number: \"" + source +
307 "\"", parsePosition.getErrorIndex());
308 }
309 return result;
310 }
311
312
313
314
315
316
317
318
319 public Complex parse(String source, ParsePosition pos) {
320 int initialIndex = pos.getIndex();
321
322
323 parseAndIgnoreWhitespace(source, pos);
324
325
326 Number re = parseNumber(source, getRealFormat(), pos);
327 if (re == null) {
328
329
330
331 pos.setIndex(initialIndex);
332 return null;
333 }
334
335
336 int startIndex = pos.getIndex();
337 char c = parseNextCharacter(source, pos);
338 int sign = 0;
339 switch (c) {
340 case 0 :
341
342
343 return new Complex(re.doubleValue(), 0.0);
344 case '-' :
345 sign = -1;
346 break;
347 case '+' :
348 sign = 1;
349 break;
350 default :
351
352
353
354 pos.setIndex(initialIndex);
355 pos.setErrorIndex(startIndex);
356 return null;
357 }
358
359
360 parseAndIgnoreWhitespace(source, pos);
361
362
363 Number im = parseNumber(source, getRealFormat(), pos);
364 if (im == null) {
365
366
367
368 pos.setIndex(initialIndex);
369 return null;
370 }
371
372
373 int n = getImaginaryCharacter().length();
374 startIndex = pos.getIndex();
375 int endIndex = startIndex + n;
376 if (source.substring(startIndex, endIndex).compareTo(
377 getImaginaryCharacter()) != 0) {
378
379
380 pos.setIndex(initialIndex);
381 pos.setErrorIndex(startIndex);
382 return null;
383 }
384 pos.setIndex(endIndex);
385
386 return new Complex(re.doubleValue(), im.doubleValue() * sign);
387 }
388
389
390
391
392
393
394
395
396 private void parseAndIgnoreWhitespace(String source, ParsePosition pos) {
397 parseNextCharacter(source, pos);
398 pos.setIndex(pos.getIndex() - 1);
399 }
400
401
402
403
404
405
406
407
408 private char parseNextCharacter(String source, ParsePosition pos) {
409 int index = pos.getIndex();
410 int n = source.length();
411 char ret = 0;
412
413 if (index < n) {
414 char c;
415 do {
416 c = source.charAt(index++);
417 } while (Character.isWhitespace(c) && index < n);
418 pos.setIndex(index);
419
420 if (index < n) {
421 ret = c;
422 }
423 }
424
425 return ret;
426 }
427
428
429
430
431
432
433
434
435
436
437 private Number parseNumber(String source, double value, ParsePosition pos) {
438 Number ret = null;
439
440 StringBuffer sb = new StringBuffer();
441 sb.append('(');
442 sb.append(value);
443 sb.append(')');
444
445 int n = sb.length();
446 int startIndex = pos.getIndex();
447 int endIndex = startIndex + n;
448 if (endIndex < source.length()) {
449 if (source.substring(startIndex, endIndex).compareTo(sb.toString()) == 0) {
450 ret = new Double(value);
451 pos.setIndex(endIndex);
452 }
453 }
454
455 return ret;
456 }
457
458
459
460
461
462
463
464
465
466
467
468 private Number parseNumber(String source, NumberFormat format, ParsePosition pos) {
469 int startIndex = pos.getIndex();
470 Number number = getRealFormat().parse(source, pos);
471 int endIndex = pos.getIndex();
472
473
474 if (startIndex == endIndex) {
475
476 double[] special = {Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY};
477 for (int i = 0; i < special.length; ++i) {
478 number = parseNumber(source, special[i], pos);
479 if (number != null) {
480 break;
481 }
482 }
483 }
484
485 return number;
486 }
487
488
489
490
491
492
493
494
495
496 public Object parseObject(String source, ParsePosition pos) {
497 return parse(source, pos);
498 }
499
500
501
502
503
504
505 public void setImaginaryCharacter(String imaginaryCharacter) {
506 if (imaginaryCharacter == null || imaginaryCharacter.length() == 0) {
507 throw new IllegalArgumentException(
508 "imaginaryCharacter must be a non-empty string.");
509 }
510 this.imaginaryCharacter = imaginaryCharacter;
511 }
512
513
514
515
516
517
518
519 public void setImaginaryFormat(NumberFormat imaginaryFormat) {
520 if (imaginaryFormat == null) {
521 throw new IllegalArgumentException(
522 "imaginaryFormat can not be null.");
523 }
524 this.imaginaryFormat = imaginaryFormat;
525 }
526
527
528
529
530
531
532
533 public void setRealFormat(NumberFormat realFormat) {
534 if (realFormat == null) {
535 throw new IllegalArgumentException(
536 "realFormat can not be null.");
537 }
538 this.realFormat = realFormat;
539 }
540 }