source: release-kits/wirk3/ant-scripts/tasks/antelope/src/ise/antelope/tasks/util/math/Math.java@ 15023

Last change on this file since 15023 was 15023, checked in by oranfry, 16 years ago

did the bulk of the work on wirk3

File size: 32.1 KB
Line 
1package ise.antelope.tasks.util.math;
2
3import java.lang.reflect.Method;
4import java.lang.reflect.Array;
5import java.lang.reflect.InvocationTargetException;
6import java.math.BigInteger;
7import java.math.BigDecimal;
8import java.util.Vector;
9import java.util.Enumeration;
10
11/**
12 * Provides access to java.lang.Math and java.lang.StrictMath for Ant. Provides
13 * add, subtract, multiply, divide and mod methods as well as access to all methods
14 * java.lang.Math and java.lang.StrictMath via reflection.
15 * <p>Copyright 2003, Dale Anson, all rights reserved
16 * @author Dale Anson, [email protected]
17 */
18public class Math {
19
20 private boolean strict = false;
21
22 public static Class BIGDECIMAL_TYPE;
23 public static Class BIGINT_TYPE;
24 static {
25 try {
26 BIGDECIMAL_TYPE = Class.forName( "java.math.BigDecimal" );
27 }
28 catch ( ClassNotFoundException e ) {
29 BIGDECIMAL_TYPE = null;
30 }
31 try {
32 BIGINT_TYPE = Class.forName( "java.math.BigInteger" );
33 }
34 catch ( Exception e ) {
35 BIGINT_TYPE = null;
36 }
37 }
38
39 public Math() {}
40
41 public Math( boolean strict ) {
42 this.strict = strict;
43 }
44
45 public void setStrict( boolean strict ) {
46 this.strict = strict;
47 }
48
49 public boolean isStrict() {
50 return strict;
51 }
52
53 public static BigDecimal add( BigDecimal a, BigDecimal b ) {
54 return a.add( b );
55 }
56
57 public static BigInteger add( BigInteger a, BigInteger b ) {
58 return a.add( b );
59 }
60
61 public static BigInteger and( BigInteger a, BigInteger b ) {
62 return a.and( b );
63 }
64
65 public static int and( int a, int b ) {
66 return a & b;
67 }
68
69 public static BigInteger or( BigInteger a, BigInteger b ) {
70 return a.or( b );
71 }
72
73 public static int or( int a, int b ) {
74 return a | b;
75 }
76
77 public static BigInteger not( BigInteger a ) {
78 return a.not();
79 }
80
81 public static int not( int a ) {
82 return ~a;
83 }
84
85 public static BigInteger xor( BigInteger a, BigInteger b ) {
86 return a.xor( b );
87 }
88
89 public static int xor( int a, int b ) {
90 return a ^ b;
91 }
92
93 public static double add( double a, double b ) {
94 return a + b;
95 }
96 public static float add( float a, float b ) {
97 return a + b;
98 }
99 public static long add( long a, long b ) {
100 return a + b;
101 }
102 public static int add( int a, int b ) {
103 return a + b;
104 }
105 public static BigInteger add( BigInteger[] a ) {
106 if ( a.length == 0 )
107 throw new IllegalArgumentException();
108 if ( a.length == 1 )
109 return a[ 0 ];
110 BigInteger b = a[ 0 ];
111 for ( int i = 1; i < a.length; i++ )
112 b = b.add( a[ i ] );
113 return b;
114 }
115 public static double add( double[] a ) {
116 if ( a.length == 0 )
117 throw new IllegalArgumentException();
118 if ( a.length == 1 )
119 return a[ 0 ];
120 double b = a[ 0 ];
121 for ( int i = 1; i < a.length; i++ )
122 b += a[ i ];
123 return b;
124 }
125 public static float add( float[] a ) {
126 if ( a.length == 0 )
127 throw new IllegalArgumentException();
128 if ( a.length == 1 )
129 return a[ 0 ];
130 float b = a[ 0 ];
131 for ( int i = 1; i < a.length; i++ )
132 b += a[ i ];
133 return b;
134 }
135 public static long add( long[] a ) {
136 if ( a.length == 0 )
137 throw new IllegalArgumentException();
138 if ( a.length == 1 )
139 return a[ 0 ];
140 long b = a[ 0 ];
141 for ( int i = 1; i < a.length; i++ )
142 b += a[ i ];
143 return b;
144 }
145 public static int add( int[] a ) {
146 if ( a.length == 0 )
147 throw new IllegalArgumentException();
148 if ( a.length == 1 )
149 return a[ 0 ];
150 int b = a[ 0 ];
151 for ( int i = 1; i < a.length; i++ )
152 b += a[ i ];
153 return b;
154 }
155
156 public static BigDecimal subtract( BigDecimal a, BigDecimal b ) {
157 return a.subtract( b );
158 }
159
160 public static BigInteger subtract( BigInteger a, BigInteger b ) {
161 return a.subtract( b );
162 }
163
164 public static double subtract( double a, double b ) {
165 return a - b;
166 }
167 public static float subtract( float a, float b ) {
168 return a - b;
169 }
170 public static long subtract( long a, long b ) {
171 return a - b;
172 }
173 public static int subtract( int a, int b ) {
174 return a - b;
175 }
176 public static BigDecimal subtract( BigDecimal[] a ) {
177 if ( a.length == 0 )
178 throw new IllegalArgumentException();
179 if ( a.length == 1 )
180 return a[ 0 ];
181 BigDecimal b = a[ 0 ];
182 for ( int i = 1; i < a.length; i++ )
183 b = b.subtract( a[ i ] );
184 return b;
185 }
186 public static BigInteger subtract( BigInteger[] a ) {
187 if ( a.length == 0 )
188 throw new IllegalArgumentException();
189 if ( a.length == 1 )
190 return a[ 0 ];
191 BigInteger b = a[ 0 ];
192 for ( int i = 1; i < a.length; i++ )
193 b = b.subtract( a[ i ] );
194 return b;
195 }
196 public static double subtract( double[] a ) {
197 if ( a.length == 0 )
198 throw new IllegalArgumentException();
199 if ( a.length == 1 )
200 return a[ 0 ];
201 double b = a[ 0 ];
202 for ( int i = 1; i < a.length; i++ )
203 b -= a[ i ];
204 return b;
205 }
206 public static float subtract( float[] a ) {
207 if ( a.length == 0 )
208 throw new IllegalArgumentException();
209 if ( a.length == 1 )
210 return a[ 0 ];
211 float b = a[ 0 ];
212 for ( int i = 1; i < a.length; i++ )
213 b -= a[ i ];
214 return b;
215 }
216 public static long subtract( long[] a ) {
217 if ( a.length == 0 )
218 throw new IllegalArgumentException();
219 if ( a.length == 1 )
220 return a[ 0 ];
221 long b = a[ 0 ];
222 for ( int i = 1; i < a.length; i++ )
223 b -= a[ i ];
224 return b;
225 }
226 public static int subtract( int[] a ) {
227 if ( a.length == 0 )
228 throw new IllegalArgumentException();
229 if ( a.length == 1 )
230 return a[ 0 ];
231 int b = a[ 0 ];
232 for ( int i = 1; i < a.length; i++ )
233 b -= a[ i ];
234 return b;
235 }
236
237 public static BigDecimal multiply( BigDecimal a, BigDecimal b ) {
238 return a.multiply( b );
239 }
240
241 public static BigInteger multiply( BigInteger a, BigInteger b ) {
242 return a.multiply( b );
243 }
244
245 public static double multiply( double a, double b ) {
246 return a * b;
247 }
248 public static float multiply( float a, float b ) {
249 return a * b;
250 }
251 public static long multiply( long a, long b ) {
252 return a * b;
253 }
254 public static int multiply( int a, int b ) {
255 return a * b;
256 }
257 public static BigDecimal multiply( BigDecimal[] a ) {
258 if ( a.length == 0 )
259 throw new IllegalArgumentException();
260 if ( a.length == 1 )
261 return a[ 0 ];
262 BigDecimal b = a[ 0 ];
263 for ( int i = 1; i < a.length; i++ )
264 b = b.multiply( a[ i ] );
265 return b;
266 }
267 public static BigInteger multiply( BigInteger[] a ) {
268 if ( a.length == 0 )
269 throw new IllegalArgumentException();
270 if ( a.length == 1 )
271 return a[ 0 ];
272 BigInteger b = a[ 0 ];
273 for ( int i = 1; i < a.length; i++ )
274 b = b.multiply( a[ i ] );
275 return b;
276 }
277 public static double multiply( double[] a ) {
278 if ( a.length == 0 )
279 throw new IllegalArgumentException();
280 if ( a.length == 1 )
281 return a[ 0 ];
282 double b = a[ 0 ];
283 for ( int i = 1; i < a.length; i++ )
284 b *= a[ i ];
285 return b;
286 }
287 public static float multiply( float[] a ) {
288 if ( a.length == 0 )
289 throw new IllegalArgumentException();
290 if ( a.length == 1 )
291 return a[ 0 ];
292 float b = a[ 0 ];
293 for ( int i = 1; i < a.length; i++ )
294 b *= a[ i ];
295 return b;
296 }
297 public static long multiply( long[] a ) {
298 if ( a.length == 0 )
299 throw new IllegalArgumentException();
300 if ( a.length == 1 )
301 return a[ 0 ];
302 long b = a[ 0 ];
303 for ( int i = 1; i < a.length; i++ )
304 b *= a[ i ];
305 return b;
306 }
307 public static int multiply( int[] a ) {
308 if ( a.length == 0 )
309 throw new IllegalArgumentException();
310 if ( a.length == 1 )
311 return a[ 0 ];
312 int b = a[ 0 ];
313 for ( int i = 1; i < a.length; i++ )
314 b *= a[ i ];
315 return b;
316 }
317
318 public static BigDecimal divide( BigDecimal a, BigDecimal b ) {
319 try {
320 return a.divide( b, BigDecimal.ROUND_HALF_EVEN );
321 }
322 catch ( Throwable e ) {
323 return a.divide( b, BigDecimal.ROUND_HALF_EVEN );
324 }
325 }
326
327 public static BigInteger divide( BigInteger a, BigInteger b ) {
328 return a.divide( b );
329 }
330
331 public static double divide( double a, double b ) {
332 if (b == 0)
333 throw new ArithmeticException("/ by zero");
334 return a / b;
335 }
336 public static float divide( float a, float b ) {
337 if (b == 0)
338 throw new ArithmeticException("/ by zero");
339 return a / b;
340 }
341 public static long divide( long a, long b ) {
342 if (b == 0)
343 throw new ArithmeticException("/ by zero");
344 return a / b;
345 }
346 public static int divide( int a, int b ) {
347 if (b == 0)
348 throw new ArithmeticException("/ by zero");
349 return a / b;
350 }
351 public static BigDecimal divide( BigDecimal[] a ) {
352 if ( a.length == 0 )
353 throw new IllegalArgumentException();
354 if ( a.length == 1 )
355 return a[ 0 ];
356 BigDecimal b = a[ 0 ];
357 for ( int i = 1; i < a.length; i++ )
358 b = b.divide( a[ i ], BigDecimal.ROUND_HALF_EVEN );
359 return b;
360 }
361 public static BigInteger divide( BigInteger[] a ) {
362 if ( a.length == 0 )
363 throw new IllegalArgumentException();
364 if ( a.length == 1 )
365 return a[ 0 ];
366 BigInteger b = a[ 0 ];
367 for ( int i = 1; i < a.length; i++ )
368 b = b.divide( a[ i ] );
369 return b;
370 }
371 public static double divide( double[] a ) {
372 if ( a.length == 0 )
373 throw new IllegalArgumentException();
374 if ( a.length == 1 )
375 return a[ 0 ];
376 double b = a[ 0 ];
377 for ( int i = 1; i < a.length; i++ ) {
378 if (a[i] == 0)
379 throw new ArithmeticException("/ by zero");
380 b /= a[ i ];
381 }
382 return b;
383 }
384 public static float divide( float[] a ) {
385 if ( a.length == 0 )
386 throw new IllegalArgumentException();
387 if ( a.length == 1 )
388 return a[ 0 ];
389 float b = a[ 0 ];
390 for ( int i = 1; i < a.length; i++ ) {
391 if (a[i] == 0)
392 throw new ArithmeticException("/ by zero");
393 b /= a[ i ];
394 }
395 return b;
396 }
397 public static long divide( long[] a ) {
398 if ( a.length == 0 )
399 throw new IllegalArgumentException();
400 if ( a.length == 1 )
401 return a[ 0 ];
402 long b = a[ 0 ];
403 for ( int i = 1; i < a.length; i++ ) {
404 if (a[i] == 0)
405 throw new ArithmeticException("/ by zero");
406 b /= a[ i ];
407 }
408 return b;
409 }
410 public static int divide( int[] a ) {
411 if ( a.length == 0 )
412 throw new IllegalArgumentException();
413 if ( a.length == 1 )
414 return a[ 0 ];
415 int b = a[ 0 ];
416 for ( int i = 1; i < a.length; i++ ) {
417 if (a[i] == 0)
418 throw new ArithmeticException("/ by zero");
419 b /= a[ i ];
420 }
421 return b;
422 }
423
424 public static BigInteger mod( BigInteger a, BigInteger b ) {
425 return a.mod( b );
426 }
427
428 public static double mod( double a, double b ) {
429 return a % b;
430 }
431 public static float mod( float a, float b ) {
432 return a % b;
433 }
434 public static long mod( long a, long b ) {
435 return a % b;
436 }
437 public static int mod( int a, int b ) {
438 return a % b;
439 }
440 public static BigInteger mod( BigInteger[] a ) {
441 if ( a.length == 0 )
442 throw new IllegalArgumentException();
443 if ( a.length == 1 )
444 return a[ 0 ];
445 BigInteger b = a[ 0 ];
446 for ( int i = 1; i < a.length; i++ )
447 b = b.mod( a[ i ] );
448 return b;
449 }
450 public static double mod( double[] a ) {
451 if ( a.length == 0 )
452 throw new IllegalArgumentException();
453 if ( a.length == 1 )
454 return a[ 0 ];
455 double b = a[ 0 ];
456 for ( int i = 1; i < a.length; i++ )
457 b %= a[ i ];
458 return b;
459 }
460 public static float mod( float[] a ) {
461 if ( a.length == 0 )
462 throw new IllegalArgumentException();
463 if ( a.length == 1 )
464 return a[ 0 ];
465 float b = a[ 0 ];
466 for ( int i = 1; i < a.length; i++ )
467 b %= a[ i ];
468 return b;
469 }
470 public static long mod( long[] a ) {
471 if ( a.length == 0 )
472 throw new IllegalArgumentException();
473 if ( a.length == 1 )
474 return a[ 0 ];
475 long b = a[ 0 ];
476 for ( int i = 1; i < a.length; i++ )
477 b %= a[ i ];
478 return b;
479 }
480 public static int mod( int[] a ) {
481 if ( a.length == 0 )
482 throw new IllegalArgumentException();
483 if ( a.length == 1 )
484 return a[ 0 ];
485 int b = a[ 0 ];
486 for ( int i = 1; i < a.length; i++ )
487 b %= a[ i ];
488 return b;
489 }
490
491 // comparisons
492 public static boolean greaterThan(int x, int y) {
493 return x > y;
494 }
495 public static boolean greaterThan(long x, long y) {
496 return x > y;
497 }
498 public static boolean greaterThan(double x, double y) {
499 return x > y;
500 }
501 public static boolean greaterThan(BigInteger x, BigInteger y) {
502 return x.compareTo(y) > 0;
503 }
504 public static boolean greaterThan(BigDecimal x, BigDecimal y) {
505 return x.compareTo(y) > 0;
506 }
507 public static boolean lessThan(int x, int y) {
508 return x < y;
509 }
510 public static boolean lessThan(long x, long y) {
511 return x < y;
512 }
513 public static boolean lessThan(double x, double y) {
514 return x < y;
515 }
516 public static boolean lessThan(BigInteger x, BigInteger y) {
517 return x.compareTo(y) < 0;
518 }
519 public static boolean lessThan(BigDecimal x, BigDecimal y) {
520 return x.compareTo(y) < 0;
521 }
522 public static boolean equal(int x, int y) {
523 return x == y;
524 }
525 public static boolean equal(long x, long y) {
526 return x == y;
527 }
528 public static boolean equal(double x, double y) {
529 return x == y;
530 }
531 public static boolean equal(BigInteger x, BigInteger y) {
532 return x.compareTo(y) == 0;
533 }
534 public static boolean equal(BigDecimal x, BigDecimal y) {
535 return x.compareTo(y) == 0;
536 }
537 public static boolean notEqual(int x, int y) {
538 return x != y;
539 }
540 public static boolean notEqual(long x, long y) {
541 return x != y;
542 }
543 public static boolean notEqual(double x, double y) {
544 return x != y;
545 }
546 public static boolean notEqual(BigInteger x, BigInteger y) {
547 return x.compareTo(y) != 0;
548 }
549 public static boolean notEqual(BigDecimal x, BigDecimal y) {
550 return x.compareTo(y) != 0;
551 }
552
553 public static BigInteger factorial( BigInteger x ) {
554 if ( x.compareTo( new BigInteger( "0" ) ) < 0 )
555 throw new IllegalArgumentException( "number must be greater than 0" );
556 BigInteger y = x;
557 for ( x = x.subtract( new BigInteger( "1" ) ); x.toString().compareTo( "1" ) > 0; x = x.subtract( new BigInteger( "1" ) ) ) {
558 y = y.multiply( x );
559 }
560 return y;
561 }
562
563 public static int factorial( double x ) {
564 return factorial( ( int ) x );
565 }
566
567 public static int factorial( float x ) {
568 return factorial( ( int ) x );
569 }
570
571 public static int factorial( int x ) {
572 if ( x < 0 )
573 throw new IllegalArgumentException( "number must be greater than 0" );
574 int y = x;
575 for ( x -= 1; x > 1; x-- )
576 y *= x;
577 return y;
578 }
579
580 public static BigDecimal min( BigDecimal a, BigDecimal b ) {
581 return a.min( b );
582 }
583
584 public static BigInteger min( BigInteger a, BigInteger b ) {
585 return a.min( b );
586 }
587
588 public static BigDecimal max( BigDecimal a, BigDecimal b ) {
589 return a.max( b );
590 }
591
592 public static BigInteger max( BigInteger a, BigInteger b ) {
593 return a.max( b );
594 }
595
596 /**
597 * y raised to the x power
598 */
599 public static BigInteger pow( BigInteger y, BigInteger x ) {
600 int exp = x.intValue();
601 if ( exp < 1 )
602 throw new IllegalArgumentException( "Exponent must be greater than 0" );
603 return y.pow( x.intValue() );
604 }
605
606 /**
607 * y raised to the x power
608 */
609 public static BigDecimal pow( BigDecimal y, BigDecimal x ) {
610 if ( x.compareTo( new BigDecimal( "1" ) ) <= 0 ) {
611 throw new ArithmeticException( "Powers of BigDecimals must be integers greater than 1" );
612 }
613 String exp = x.toString();
614 if ( exp.indexOf( "." ) > 0 )
615 exp = exp.substring( 0, exp.indexOf( "." ) );
616 BigInteger e = new BigInteger( exp );
617 BigDecimal z = new BigDecimal( y.toString() );
618 for ( ;e.compareTo( BigInteger.ONE ) > 0; e = e.subtract( BigInteger.ONE ) ) {
619 y = y.multiply( z );
620 }
621 return y;
622 }
623
624 /**
625 * Do a mathematical calculation. The allowed operations are all
626 * operations supported by java.lang.Math and this class. Assumes data
627 * type is "double".
628 * @param op the name of a mathematical operation to perform
629 * @param operands the operands for the operation, these strings must parse to numbers.
630 */
631 public Number calculate( String op, String[] operands ) {
632 return calculate( op, "double", operands );
633 }
634
635 /**
636 * Do a mathematical calculation. The allowed operations are all
637 * operations supported by java.lang.Math.
638 * @param op the name of a mathematical operation to perform
639 * @param type the data type of the operands
640 * @param operands the operands for the operation
641 * @return the result of the calculation. For boolean operations, returns
642 * 1 for true, 0 for false;
643 */
644 public Number calculate( String op, String type, String[] operands ) {
645 try {
646 if ( operands.length >= 2 && ( op.equals( "add" ) ||
647 op.equals( "subtract" ) ||
648 op.equals( "multiply" ) ||
649 op.equals( "divide" ) ||
650 op.equals( "mod" ) ) ) {
651 return calculateArray( op, type, operands );
652 }
653
654 if ( operands.length > 2 )
655 throw new IllegalArgumentException( "too many operands" );
656
657 Class c;
658 Method m;
659 if ( strict )
660 c = Class.forName( "java.lang.StrictMath" );
661 else
662 c = Class.forName( "java.lang.Math" );
663
664 // check if op is 'random'. Random is a special case in that it is
665 // the only method in Math that takes no parameters.
666 if ( op.equals( "random" ) ) {
667 m = c.getDeclaredMethod( op, new Class[] {} );
668 Object result = m.invoke( c, null );
669 return ( Number ) result;
670 }
671
672 // find candidate methods for the requested operation
673 Vector candidates = new Vector();
674 Method[] methods = c.getDeclaredMethods();
675 for ( int i = 0; i < methods.length; i++ ) {
676 String name = methods[ i ].getName();
677 if ( name.equals( op ) ) {
678 candidates.addElement( new Candidate( c, methods[ i ] ) );
679 }
680 }
681
682 // also look for candidate methods in this class
683 c = this.getClass();
684 methods = c.getDeclaredMethods();
685 for ( int i = 0; i < methods.length; i++ ) {
686 String name = methods[ i ].getName();
687 if ( name.equals( op ) ) {
688 candidates.addElement( new Candidate( c, methods[ i ] ) );
689 }
690 }
691
692 if ( candidates.size() == 0 )
693 throw new RuntimeException( "Unknown operation: " + op );
694
695 // get the desired data type for the operation, default is
696 // Double.TYPE if no other match is found
697 Class wantTypeClass = getDataType( type );
698
699 // get the parameter count for the candidate methods -- in Math,
700 // all like named methods have the same number of parameters, just
701 // the data types are different. (Fix for bug # 724812 -- the above
702 // statement is true of java.lang.Math, but not of this class.)
703 //int paramCount = ( ( Method ) candidates.elementAt( 0 ) ).getParameterTypes().length;
704 int paramCount = -1;
705 try {
706 for ( int i = 0; i <= candidates.size(); i++ ) {
707 Candidate candidate = ( Candidate ) candidates.elementAt( i );
708 Method method = candidate.getCandidateMethod();
709 paramCount = method.getParameterTypes().length;
710 if ( paramCount == operands.length )
711 break;
712 }
713 }
714 catch ( Exception e ) {
715 throw new RuntimeException( "Wrong number of arguments, have " +
716 operands.length + ", but can't find corresponding method." );
717 }
718
719 // make sure there are enough arguments to pass to the method
720 // see bug fix above, this is no longer necessary
721 //if ( operands.length != paramCount )
722 // throw new RuntimeException( "Wrong number of arguments, have " +
723 // operands.length + ", expected " + paramCount );
724
725 // determine the actual type class for the method to invoke.
726 // Some methods have only one implementation so determine the
727 // typeClass from the method itself, not the desired.
728 Class typeClass = null;
729 if ( candidates.size() == 1 ) {
730 Candidate candidate = ( Candidate ) candidates.elementAt( 0 );
731 c = candidate.getCandidateClass();
732 m = candidate.getCandidateMethod();
733 typeClass = m.getParameterTypes() [ 0 ];
734 }
735 else {
736 // check each candidate to find one with the desired type
737 Enumeration en = candidates.elements();
738 while ( en.hasMoreElements() ) {
739 Candidate candidate = ( Candidate ) en.nextElement();
740 c = candidate.getCandidateClass();
741 m = candidate.getCandidateMethod();
742 if ( m.getParameterTypes() [ 0 ].equals( wantTypeClass ) ) {
743 typeClass = wantTypeClass;
744 break;
745 }
746 }
747 if ( typeClass == null )
748 throw new RuntimeException( "Can't find a method with parameters of type " + type );
749 }
750
751 // get the method to invoke
752 Class[] paramTypes = new Class[ paramCount ];
753 for ( int i = 0; i < paramCount; i++ ) {
754 paramTypes[ i ] = typeClass;
755 }
756 m = c.getDeclaredMethod( op, paramTypes );
757 //System.out.println( "Math.calculate, invoking: " + m.toString() );
758
759 // load the parameters and invoke the method
760 Object[] params = getParams( typeClass, operands );
761
762 try {
763 //System.out.println( "Math.calculateArray, invoking: " + m.toString() );
764 Object result = m.invoke( c, params );
765 if (result instanceof Boolean) {
766 result = new Integer(((Boolean)result).booleanValue() ? 1 : 0);
767 }
768 return ( Number ) result;
769 }
770 catch ( InvocationTargetException ite ) {
771 Throwable t = ite.getCause();
772 if ( t != null && t instanceof ArithmeticException ) {
773 throw ( ArithmeticException ) t;
774 }
775 else {
776 throw ite;
777 }
778 }
779 }
780 catch ( Exception e ) {
781 if ( e instanceof RuntimeException )
782 throw ( RuntimeException ) e;
783 }
784 return null;
785 }
786
787 /**
788 * Performs a calculation on an array of numbers. The mathematical methods
789 * in this class will accept an array of numbers, so
790 * <code>add(new int[]{1, 2, 3})</code>
791 * is equivalent to
792 * <code>add(add(1, 2), 3)</code>
793 * which is equivalent to 1 + 2 + 3.
794 * @param op the operation to perform
795 * @type the data type of the operands. All operands will be cast to the same
796 * data type
797 * @param operands these strings must parse to numbers.
798 */
799 private Number calculateArray( String op, String type, String[] operands ) {
800 try {
801 Class c = this.getClass();
802
803 // find candidate methods for the requested operation
804 Vector candidates = new Vector();
805 Method[] methods = c.getDeclaredMethods();
806 for ( int i = 0; i < methods.length; i++ ) {
807 String name = methods[ i ].getName();
808 if ( name.equals( op ) ) {
809 if ( methods[ i ].getParameterTypes().length == 1 ) {
810 if ( methods[ i ].getParameterTypes() [ 0 ].isArray() )
811 candidates.addElement( methods[ i ] );
812 }
813 }
814 }
815 if ( candidates.size() == 0 )
816 throw new RuntimeException( "Unknown operation: " + op );
817
818 // get the desired data type for the operation, default is
819 // Double.TYPE if no other match is found
820 Object wantTypeClass = getDataTypeArray( type, operands.length );
821
822 // find the actual method to invoke and invoke it immediately once
823 // it is found
824 Class typeClass = null;
825 Enumeration en = candidates.elements();
826 while ( en.hasMoreElements() ) {
827 Method m = ( Method ) en.nextElement();
828 if ( m.getParameterTypes() [ 0 ].equals( wantTypeClass.getClass() ) ) {
829 typeClass = getDataType( type );
830 Object[] params = getParamsArray( typeClass, operands );
831 try {
832 //System.out.println( "Math.calculateArray, invoking: " + m.toString() );
833 Object result = m.invoke( c, params );
834 return ( Number ) result;
835 }
836 catch ( InvocationTargetException ite ) {
837 Throwable t = ite.getCause();
838 if ( t != null && t instanceof ArithmeticException ) {
839 //System.out.println( "caught ArithmeticException in Math" );
840 throw ( ArithmeticException ) t;
841 }
842 else {
843 //System.out.println( "throwing " + ite.getMessage() );
844 throw ite;
845 }
846 }
847 }
848 }
849 }
850 catch ( Exception e ) {
851 //e.printStackTrace();
852 if ( e instanceof ArithmeticException ) {
853 //System.out.println("rethrowing " + e.getMessage());
854 throw ( ArithmeticException ) e;
855 }
856 }
857 return null;
858 }
859
860 /**
861 * Converts a string representing a data type into the actual type.
862 * @param type one of "int", "long", "float", or "double"
863 * @return one of Integer.TYPE, Long.TYPE, Float.TYPE, or Double.TYPE. If the
864 * given type is null or not one of the allowed types, Double.TYPE will be
865 * returned.
866 */
867 private Class getDataType( String type ) {
868 if ( type == null )
869 return Double.TYPE;
870 if ( type.equals( "int" ) ) {
871 return Integer.TYPE;
872 }
873 else if ( type.equals( "long" ) ) {
874 return Long.TYPE;
875 }
876 else if ( type.equals( "float" ) ) {
877 return Float.TYPE;
878 }
879 else if ( type.equals( "bigint" ) ) {
880 try {
881 return Class.forName( "java.math.BigInteger" );
882 }
883 catch ( Exception e ) {
884 //e.printStackTrace();
885 }
886 }
887 else if ( type.equals( "bigdecimal" ) ) {
888 try {
889 return Class.forName( "java.math.BigDecimal" );
890 }
891 catch ( Exception e ) {
892 //e.printStackTrace();
893 }
894 }
895 return Double.TYPE;
896 }
897
898 /**
899 * Converts a string representing a data type into an Array.
900 * @param type one of "int", "long", "float", or "double"
901 * @param length how long to make the array
902 * @return an Array representing the data type
903 */
904 private Object getDataTypeArray( String type, int length ) {
905 if ( type == null )
906 return Array.newInstance( Double.TYPE, length );
907 if ( type.equals( "int" ) ) {
908 return Array.newInstance( Integer.TYPE, length );
909 }
910 else if ( type.equals( "long" ) ) {
911 return Array.newInstance( Long.TYPE, length );
912 }
913 else if ( type.equals( "float" ) ) {
914 return Array.newInstance( Float.TYPE, length );
915 }
916 else if ( type.equals( "bigdecimal" ) ) {
917 return Array.newInstance( BIGDECIMAL_TYPE, length );
918 }
919 else if ( type.equals( "bigint" ) ) {
920 return Array.newInstance( BIGINT_TYPE, length );
921 }
922 else {
923 return Array.newInstance( Double.TYPE, length );
924 }
925 }
926
927 /**
928 * @returns the given operands as an array of the given type.
929 */
930 private Object[] getParams( Class typeClass, String[] operands ) {
931 int paramCount = operands.length;
932 Object[] params = new Object[ paramCount ];
933 if ( typeClass == BIGDECIMAL_TYPE ) {
934 for ( int i = 0; i < paramCount; i++ ) {
935 params[ i ] = new BigDecimal( operands[ i ] );
936 }
937 }
938 else if ( typeClass == BIGINT_TYPE ) {
939 for ( int i = 0; i < paramCount; i++ ) {
940 params[ i ] = new BigInteger( operands[ i ] );
941 }
942 }
943 else if ( typeClass == Double.TYPE ) {
944 for ( int i = 0; i < paramCount; i++ ) {
945 params[ i ] = new Double( operands[ i ] );
946 }
947 }
948 else if ( typeClass == Long.TYPE ) {
949 for ( int i = 0; i < paramCount; i++ ) {
950 params[ i ] = new Long( operands[ i ] );
951 }
952 }
953 else if ( typeClass == Float.TYPE ) {
954 for ( int i = 0; i < paramCount; i++ ) {
955 params[ i ] = new Float( operands[ i ] );
956 }
957 }
958 else {
959 // Integer.TYPE is only other choice
960 for ( int i = 0; i < paramCount; i++ ) {
961 params[ i ] = new Integer( operands[ i ] );
962 }
963 }
964 if ( paramCount > 2 )
965 params = new Object[] {params};
966 return params;
967 }
968
969 /**
970 * Converts the given operands into an array of the given type.
971 */
972 private Object[] getParamsArray( Class typeClass, String[] operands ) {
973 int paramCount = operands.length;
974 if ( typeClass == BIGDECIMAL_TYPE ) {
975 BigDecimal[] array = ( BigDecimal[] ) Array.newInstance( typeClass, operands.length );
976 for ( int i = 0; i < paramCount; i++ ) {
977 array[ i ] = new BigDecimal( operands[ i ] );
978 }
979 return new Object[] {array};
980 }
981 else if ( typeClass == BIGINT_TYPE ) {
982 BigInteger[] array = ( BigInteger[] ) Array.newInstance( typeClass, operands.length );
983 for ( int i = 0; i < paramCount; i++ ) {
984 array[ i ] = new BigInteger( operands[ i ] );
985 }
986 return new Object[] {array};
987 }
988 else if ( typeClass == Double.TYPE ) {
989 double[] array = ( double[] ) Array.newInstance( typeClass, operands.length );
990 for ( int i = 0; i < paramCount; i++ ) {
991 Array.setDouble( array, i, new Double( operands[ i ] ).doubleValue() );
992 }
993 return new Object[] {array};
994 }
995 else if ( typeClass == Long.TYPE ) {
996 long[] array = ( long[] ) Array.newInstance( typeClass, operands.length );
997 for ( int i = 0; i < paramCount; i++ ) {
998 Array.setLong( array, i, new Long( operands[ i ] ).longValue() );
999 }
1000 return new Object[] {array};
1001 }
1002 else if ( typeClass == Float.TYPE ) {
1003 float[] array = ( float[] ) Array.newInstance( typeClass, operands.length );
1004 for ( int i = 0; i < paramCount; i++ ) {
1005 Array.setFloat( array, i, new Float( operands[ i ] ).floatValue() );
1006 }
1007 return new Object[] {array};
1008 }
1009 else {
1010 // Integer.TYPE is only other choice
1011 Object array = Array.newInstance( typeClass, operands.length );
1012 for ( int i = 0; i < paramCount; i++ ) {
1013 if (operands[i].indexOf(".") > 0)
1014 operands[i] = operands[i].substring(0, operands[i].indexOf("."));
1015 Array.setInt( array, i, new Integer( operands[ i ] ).intValue() );
1016 }
1017 return new Object[] {array};
1018 }
1019 }
1020
1021 public class Candidate {
1022 private Class c;
1023 private Method m;
1024 public Candidate( Class c, Method m ) {
1025 this.c = c;
1026 this.m = m;
1027 }
1028 public Class getCandidateClass() {
1029 return c;
1030 }
1031 public Method getCandidateMethod() {
1032 return m;
1033 }
1034 }
1035}
Note: See TracBrowser for help on using the repository browser.