Source code: com/hartmath/initial/MathOperators.java
1 /*
2 * MathOperators.java
3 * Copyright (C) 2000 Klaus Hartlage
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19 package com.hartmath.initial;
20
21 import java.lang.*;
22
23 import com.hartmath.util.*;
24 import com.hartmath.domain.*;
25 import com.hartmath.mapping.*;
26 import com.hartmath.lib.C;
27 import com.hartmath.patternmatching.HRule;
28 import com.hartmath.patternmatching.HRuleSet;
29 import com.hartmath.expression.HObject;
30 import com.hartmath.expression.HString;
31 import com.hartmath.expression.HSymbol;
32 import com.hartmath.expression.HMultinomial;
33 import com.hartmath.expression.HComplex;
34 import com.hartmath.expression.HDoubleComplex;
35 import com.hartmath.expression.HDomainInstance;
36 import com.hartmath.expression.HFunction;
37 import com.hartmath.expression.HDouble;
38 import com.hartmath.expression.HSignedNumber;
39 import com.hartmath.expression.HFraction;
40 import com.hartmath.expression.HInteger;
41 import com.hartmath.exceptions.HThrowException;
42 import com.hartmath.lib.Session;
43
44 /**
45 * Class Declaration.
46 *
47 *@author Klaus Hartlage <A HREF="mailto:khartlage@t-online.de">
48 * khartlage@t-online.de</A>
49 *@created 16. Juli 2001
50 *@see
51 *@version %I%, %G%
52 */
53 class EAdd extends ESMultiArg implements FunctionOpEvaluator {
54
55 /**
56 * Method Declaration.
57 *
58 *@param o0
59 *@param o1
60 *@param session Description of Parameter
61 *@return
62 *@see
63 */
64 public HObject e2ObjArg(HObject o0, HObject o1, Session session) {
65 if ((o0 instanceof HMultinomial) && (o1 instanceof HMultinomial)) {
66 return ((HMultinomial) o0).add((HMultinomial) o1);
67 }
68 if (o0 instanceof HDomainInstance && o1 instanceof HDomainInstance) {
69 return ObjectD.binaryCall("add", ((HDomainInstance) o0),
70 ((HDomainInstance) o1));
71 }
72 // Context ct = ((ContextThread) Thread.currentThread()).getContext();
73 if (session.getNumericFlag()) {
74 if (o0.equals(C.CD0)) {
75 return o1;
76 }
77
78 if (o1.equals(C.CD0)) {
79 return o0;
80 }
81 }
82
83 if (o0.equals(C.C0)) {
84 return o1;
85 }
86
87 if (o1.equals(C.C0)) {
88 return o0;
89 }
90
91 if (o0.equals(o1)) {
92 return C.Multiply.f(C.C2, o0);
93 }
94
95 if (o0.head().equals(C.Multiply) && (((HFunction) o0).size() > 1)) {
96 HFunction f0 = (HFunction) o0;
97
98 if (((HFunction) o0).get(0).isNumber()) {
99 if ((f0.size() == 2) && f0.get(1).equals(o1)) {
100 return C.Multiply.f(C.Add.f(C.C1, f0.get(0)), o1);
101 }
102
103 if (o1.head().equals(C.Multiply) && (((HFunction) o1).size() > 1)) {
104 HFunction f1 = (HFunction) o1;
105
106 if (f1.get(0).isNumber()) {
107 if (f0.equalsFromPosition(1, f1, 1)) {
108 HFunction result =
109 new HFunction(f0, C.Multiply, 1, f0.size(), true);
110
111 return C.Multiply.f(C.Add.f(f0.get(0), f1.get(0)), result);
112 }
113 }
114 else {
115 if (f0.equalsFromPosition(1, f1, 0)) {
116 HFunction result =
117 new HFunction(f0, C.Multiply, 1, f0.size(), true);
118
119 return C.Multiply.f(C.Add.f(C.C1, f0.get(0)), result);
120 }
121 }
122 }
123 }
124 else {
125 if (o1.head().equals(C.Multiply) && (((HFunction) o1).size() > 1)) {
126 HFunction f1 = (HFunction) o1;
127
128 if (f1.get(0).isNumber()) {
129 if (f0.equalsFromPosition(0, f1, 1)) {
130 HFunction result =
131 new HFunction(f1, C.Multiply, 1, f1.size(), true);
132
133 return C.Multiply.f(C.Add.f(C.C1, f1.get(0)), result);
134 }
135 }
136 }
137 }
138 }
139
140 if (o1.head().equals(C.Multiply) && (((HFunction) o1).size() > 1) &&
141 ((HFunction) o1).get(0).isNumber()) {
142 HFunction f1 = (HFunction) o1;
143
144 if ((f1.size() == 2) && f1.get(1).equals(o0)) {
145 return C.Multiply.f(C.Add.f(C.C1, f1.get(0)), o0);
146 }
147 }
148
149 return null;
150 }
151
152
153 /**
154 * Description of the Method
155 *
156 *@param d0 Description of Parameter
157 *@param d1 Description of Parameter
158 *@param session Description of Parameter
159 *@return Description of the Returned Value
160 */
161 public HObject e2DblArg(HDouble d0, HDouble d1, Session session) {
162 return d0.add(d1);
163 }
164
165
166 /**
167 * Method Declaration.
168 *
169 *@param d0
170 *@param d1
171 *@param session Description of Parameter
172 *@return
173 *@see
174 */
175 public HObject e2DblComArg(HDoubleComplex d0, HDoubleComplex d1, Session session) {
176 return d0.add(d1);
177 }
178
179
180 /**
181 * Method Declaration.
182 *
183 *@param i0
184 *@param i1
185 *@param session Description of Parameter
186 *@return
187 *@see
188 */
189 public HObject e2IntArg(HInteger i0, HInteger i1, Session session) {
190 return i0.add(i1);
191 }
192
193
194 /**
195 * Method Declaration.
196 *
197 *@param f0
198 *@param f1
199 *@param session Description of Parameter
200 *@return
201 *@see
202 */
203 public HObject e2FraArg(HFraction f0, HFraction f1, Session session) {
204 return f0.add(f1);
205 }
206
207
208 /**
209 * Method Declaration.
210 *
211 *@param c0
212 *@param c1
213 *@param session Description of Parameter
214 *@return
215 *@see
216 */
217 public HObject e2ComArg(HComplex c0, HComplex c1, Session session) {
218 return c0.add(c1);
219 }
220
221
222 /**
223 * Method Declaration.
224 *
225 *@param c0
226 *@param i1
227 *@param session Description of Parameter
228 *@return
229 *@see
230 */
231 public HObject eComIntArg(HComplex c0, HInteger i1, Session session) {
232 return c0.add(new HComplex(i1, C.C0));
233 }
234
235
236 /**
237 * Method Declaration.
238 *
239 *@param fun
240 *@param session Description of Parameter
241 *@return
242 *@see
243 */
244 public String toOpString(HFunction fun, Session session) {
245 final int prec = C.ADD_PRECEDENCE;
246 final char ch = '+';
247 StringBuffer buf = new StringBuffer();
248 HObject temp;
249
250 if (fun.size() <= 1) {
251 // important for tracing pattern-matching
252 buf.append("Add(");
253
254 if (fun.size() == 1) {
255 fun.get(0).toStringBuffer(buf, session);
256 }
257
258 buf.append(")");
259
260 return buf.toString();
261 }
262
263 for (int i = 0; i < fun.size(); i++) {
264 temp = fun.get(i);
265
266 if (temp instanceof HFunction && (((HFunction) temp).size() > 0) &&
267 temp.head().equals(C.Multiply)) {
268 final int multPrec = C.MULTIPLY_PRECEDENCE;
269 final char multCh = '*';
270 boolean flag = false;
271 HFunction multFun = (HFunction) temp;
272 HObject temp1 = multFun.get(0);
273
274 if (temp1 instanceof HSignedNumber &&
275 ((HSignedNumber) temp1).isNegative()) {
276 if (temp1.equals(C.C1)) {
277 flag = true;
278 }
279 else {
280 if (temp1.equals(C.CD1)) {
281 flag = true;
282 }
283 else {
284 if (temp1.equals(C.CN1)) {
285 buf.append("-");
286
287 flag = true;
288 }
289 else {
290 if (temp1.equals(C.CDN1)) {
291 buf.append("-");
292
293 flag = true;
294 }
295 else {
296 // buf.append(temp1.toString());
297 temp1.toStringBuffer(buf, session);
298 }
299 }
300 }
301 }
302 }
303 else {
304 if (i > 0) {
305 buf.append(ch);
306 }
307
308 if (temp1.precedence() < multPrec) {
309 buf.append('(');
310 }
311
312 // buf.append(temp1.toString());
313 temp1.toStringBuffer(buf, session);
314
315 if (temp1.precedence() < multPrec) {
316 buf.append(')');
317 }
318 }
319
320 for (int j = 1; j < multFun.size(); j++) {
321 temp1 = multFun.get(j);
322
323 if ((j > 1) || (flag == false)) {
324 buf.append(multCh);
325 }
326
327 if (temp1.precedence() < multPrec) {
328 buf.append('(');
329 }
330
331 //buf.append(temp1.toString());
332 temp1.toStringBuffer(buf, session);
333
334 if (temp1.precedence() < multPrec) {
335 buf.append(')');
336 }
337 }
338 }
339 else {
340 if (temp instanceof HSignedNumber &&
341 ((HSignedNumber) temp).isNegative()) {
342 // special case negative number:
343 //buf.append(temp.toString());
344 temp.toStringBuffer(buf, session);
345 }
346 else {
347 if (i > 0) {
348 buf.append(ch);
349 }
350
351 if (temp.precedence() < prec) {
352 buf.append('(');
353 }
354
355 // buf.append(temp.toString());
356 temp.toStringBuffer(buf, session);
357
358 if (temp.precedence() < prec) {
359 buf.append(')');
360 }
361 }
362 }
363 }
364
365 return buf.toString();
366 }
367
368
369 /**
370 * Method Declaration.
371 *
372 *@return
373 *@see
374 */
375 public int precedence() {
376 return C.ADD_PRECEDENCE;
377 }
378
379 }
380
381 /**
382 * Description of the Class
383 *
384 *@author khartlage
385 *@created 16. Juli 2001
386 */
387 class EDot extends ESMultiArg implements FunctionOpEvaluator {
388
389
390 /**
391 * Constructor for the EDot object
392 */
393 public EDot() {
394 }
395
396
397 /**
398 * Description of the Method
399 *
400 *@param o0 Description of Parameter
401 *@param o1 Description of Parameter
402 *@param session Description of Parameter
403 *@return Description of the Returned Value
404 */
405 public HObject e2ComArg(HComplex o0, HComplex o1, Session session) {
406 return null;
407 }
408
409
410 /**
411 * Method Declaration.
412 *
413 *@param o0
414 *@param o1
415 *@param session Description of Parameter
416 *@return
417 *@see
418 */
419 public HObject e2ObjArg(HObject o0, HObject o1, Session session) {
420 if (session.EV(C.IsVector.f(o0)) == C.True) {
421 HFunction f0 = (HFunction) o0;
422 // vector
423 int v0len = f0.size();
424
425 if (session.EV(C.IsVector.f(o1)) == C.True) {
426 HFunction f1 = (HFunction) o1;
427
428 if (v0len != f1.size()) {
429 return null;
430 }
431
432 HFunction res = new HFunction(C.Add);
433
434 for (int k = 0; k < v0len; k++) {
435 res.add(C.Multiply.f(f0.get(k), f1.get(k)));
436 }
437
438 return res;
439 }
440
441 if (session.EV(C.IsMatrix.f(o1)) == C.True) {
442 HFunction f1 = (HFunction) o1;
443 HFunction g1 = (HFunction) f1.get(0);
444 int rowLen1 = f1.size();
445 int colLen1 = g1.size();
446
447 if (v0len != rowLen1) {
448 return null;
449 }
450
451 HFunction res = new HFunction(C.List);
452 HFunction rowres;
453
454 for (int k = 0; k < colLen1; k++) {
455 rowres = new HFunction(C.Add);
456
457 for (int i = 0; i < v0len; i++) {
458 rowres.add(C.Multiply.f(f0.get(i), f1.get(i, k)));
459 }
460
461 res.add(rowres);
462 }
463
464 return res;
465 }
466
467 return null;
468 }
469
470 if (session.EV(C.IsMatrix.f(o0)) == C.True) {
471 HFunction f0 = (HFunction) o0;
472 // matrix
473 HFunction g0 = (HFunction) f0.get(0);
474 // matrix-row
475
476 if (session.EV(C.IsMatrix.f(o1)) == C.True) {
477 HFunction f1 = (HFunction) o1;
478 HFunction g1 = (HFunction) f1.get(0);
479
480 // {{a,b},{c,d}}.{{e,f},{g,h}}
481 int colLen0 = g0.size();
482 int rowLen1 = f1.size();
483
484 if (colLen0 != rowLen1) {
485 return null;
486 }
487
488 HFunction res = new HFunction(C.List);
489
490 res.setProperties(HFunction.MATRIXFORM);
491
492 HFunction rowres;
493 HFunction temp;
494
495 for (int k = 0; k < f0.size(); k++) {
496 rowres = new HFunction(C.List);
497 g0 = (HFunction) f0.get(k);
498
499 for (int i = 0; i < g1.size(); i++) {
500 temp = new HFunction(C.Add);
501
502 for (int j = 0; j < colLen0; j++) {
503 g1 = (HFunction) f1.get(j);
504
505 temp.add(C.Multiply.f(g0.get(j), g1.get(i)));
506 }
507
508 rowres.add(temp);
509 }
510
511 res.add(rowres);
512 }
513
514 return res;
515 }
516
517 if (session.EV(C.IsVector.f(o1)) == C.True) {
518 HFunction f1 = (HFunction) o1;
519 int colLen1 = g0.size();
520
521 if (f1.size() != colLen1) {
522 return null;
523 }
524
525 HFunction res = new HFunction(C.List);
526 HFunction rowres;
527
528 for (int k = 0; k < f0.size(); k++) {
529 rowres = new HFunction(C.Add);
530 g0 = (HFunction) f0.get(k);
531
532 for (int i = 0; i < g0.size(); i++) {
533 rowres.add(C.Multiply.f(f1.get(i), g0.get(i)));
534 }
535
536 res.add(rowres);
537 }
538
539 return res;
540 }
541 }
542
543 return null;
544 }
545
546
547 /**
548 * Method Declaration.
549 *
550 *@param fun
551 *@param session Description of Parameter
552 *@return
553 *@see
554 */
555 public String toOpString(HFunction fun, Session session) {
556 return E2SArg.operatorString(fun, ".", C.DOT_PRECEDENCE, session);
557 }
558
559
560 /**
561 * Method Declaration.
562 *
563 *@return
564 *@see
565 */
566 public int precedence() {
567 return C.DOT_PRECEDENCE;
568 }
569
570 }
571
572 /**
573 * Class Declaration.
574 *
575 *@author Klaus Hartlage <A HREF="mailto:khartlage@t-online.de">
576 * khartlage@t-online.de</A>
577 *@created 16. Juli 2001
578 *@see
579 *@version %I%, %G%
580 */
581 class EMultiply extends E2SArg implements FunctionOpEvaluator {
582
583
584 /**
585 * Description of the Method
586 *
587 *@param vect Description of Parameter
588 *@param session Description of Parameter
589 *@return Description of the Returned Value
590 */
591 public HObject evaluate(HFunction vect, Session session) {
592 if (vect.size() == 2) {
593 if (vect.get(0) instanceof HSignedNumber &&
594 vect.get(1) instanceof HFunction &&
595 vect.get(1).head().equals(C.Add)) {
596 HFunction arg2 = (HFunction) vect.get(1);
597 HFunction result = C.Add.f();
598 for (int i = 0; i < arg2.size(); i++) {
599 result.add(C.Multiply.f(vect.get(0), arg2.get(i)));
600 }
601 return result;
602 }
603 return binaryOperator(vect.get(0), vect.get(1), session);
604 }
605
606 if (vect.size() > 2) {
607 HSymbol sym = vect.head();
608 HFunction result = new HFunction(sym);
609 HObject tres;
610 HObject temp = vect.get(0);
611 boolean evaled = false;
612 int i = 1;
613
614 while (i < vect.size()) {
615
616 // for (int i = 1; i < vect.size(); i++) {
617 tres = binaryOperator(temp, vect.get(i), session);
618
619 if (tres == null) {
620
621 // kh***
622 for (int j = i + 1; j < vect.size(); j++) {
623 tres = binaryOperator(temp, vect.get(j), session);
624
625 if (tres != null) {
626 evaled = true;
627 temp = tres;
628
629 vect.remove(j);
630
631 break;
632 }
633 }
634
635 if (tres == null) {
636
637 // kh***
638 result.add(temp);
639
640 if (i == vect.size() - 1) {
641 result.add(vect.get(i));
642 }
643 else {
644 temp = vect.get(i);
645 }
646
647 i++;
648 }
649 }
650 else {
651 evaled = true;
652 temp = tres;
653
654 if (i == (vect.size() - 1)) {
655 result.add(temp);
656 }
657
658 i++;
659 }
660 }
661
662 if (evaled) {
663 if ((result.size() == 1)
664 && sym.checkAttributes(session, HSymbol.ONEIDENTITY)) {
665 return result.get(0);
666 }
667
668 return result;
669 }
670 }
671
672 return null;
673 }
674
675
676 /**
677 * Method Declaration.
678 *
679 *@param o0
680 *@param o1
681 *@param session Description of Parameter
682 *@return
683 *@see
684 */
685 public HObject e2ObjArg(HObject o0, HObject o1, Session session) {
686 if ((o0 instanceof HMultinomial) && (o1 instanceof HMultinomial)) {
687 return ((HMultinomial) o0).multiply((HMultinomial) o1);
688 }
689 if (o0 instanceof HDomainInstance && o1 instanceof HDomainInstance) {
690 return ObjectD.binaryCall("multiply", ((HDomainInstance) o0),
691 ((HDomainInstance) o1));
692 }
693 // Context ct = ((ContextThread) Thread.currentThread()).getContext();
694 if (session.getNumericFlag()) {
695 if (o0.equals(C.CD0)) {
696 return C.CD0;
697 }
698
699 if (o1.equals(C.CD0)) {
700 return C.CD0;
701 }
702
703 if (o0.equals(C.CD1)) {
704 return o1;
705 }
706
707 if (o1.equals(C.CD1)) {
708 return o0;
709 }
710 }
711
712 if (o0.equals(C.C0)) {
713 return C.C0;
714 }
715
716 if (o1.equals(C.C0)) {
717 return C.C0;
718 }
719
720 if (o0.equals(C.C1)) {
721 return o1;
722 }
723
724 if (o1.equals(C.C1)) {
725 return o0;
726 }
727
728 if (o0.equals(o1)) {
729 return C.Pow.f(o0, C.C2);
730 }
731
732 if (o0.head().equals(C.Pow) && (((HFunction) o0).size() == 2)) {
733 HFunction f0 = (HFunction) o0;
734
735 if (f0.get(1).isNumber()) {
736 if (f0.get(0).equals(o1)) {
737 return C.Pow.f(o1, C.Add.f(C.C1, f0.get(1)));
738 }
739
740 if (o1.head().equals(C.Pow) && (((HFunction) o1).size() == 2)) {
741 HFunction f1 = (HFunction) o1;
742
743 if (f1.get(1).isNumber()) {
744 if (f0.get(0).equals(f1.get(0))) {
745 return C.Pow.f(f0.get(0), C.Add.f(f0.get(1), f1.get(1)));
746 }
747 }
748 }
749 }
750 }
751
752 if (o1.head().equals(C.Pow) && (((HFunction) o1).size() == 2) &&
753 ((HFunction) o1).get(1).isNumber()) {
754 HFunction f1 = (HFunction) o1;
755
756 if (f1.get(0).equals(o0)) {
757 return C.Pow.f(o0, C.Add.f(C.C1, f1.get(1)));
758 }
759 }
760
761 return null;
762 }
763
764
765 /**
766 * Method Declaration.
767 *
768 *@param d0
769 *@param d1
770 *@param session Description of Parameter
771 *@return
772 *@see
773 */
774 public HObject e2DblArg(HDouble d0, HDouble d1, Session session) {
775 return d0.multiply(d1);
776 }
777
778
779 /**
780 * Method Declaration.
781 *
782 *@param d0
783 *@param d1
784 *@param session Description of Parameter
785 *@return
786 *@see
787 */
788 public HObject e2DblComArg(HDoubleComplex d0, HDoubleComplex d1, Session session) {
789 return d0.multiply(d1);
790 }
791
792
793 /**
794 * Method Declaration.
795 *
796 *@param i0
797 *@param i1
798 *@param session Description of Parameter
799 *@return
800 *@see
801 */
802 public HObject e2IntArg(HInteger i0, HInteger i1, Session session) {
803 return i0.multiply(i1);
804 }
805
806
807 /**
808 * Method Declaration.
809 *
810 *@param f0
811 *@param f1
812 *@param session Description of Parameter
813 *@return
814 *@see
815 */
816 public HObject e2FraArg(HFraction f0, HFraction f1, Session session) {
817 return f0.multiply(f1);
818 }
819
820
821 /**
822 * Method Declaration.
823 *
824 *@param c0
825 *@param i1
826 *@param session Description of Parameter
827 *@return
828 *@see
829 */
830 public HObject eComIntArg(HComplex c0, HInteger i1, Session session) {
831 return c0.multiply(new HComplex(i1, C.C0));
832 }
833
834
835 /**
836 * Method Declaration.
837 *
838 *@param c0
839 *@param c1
840 *@param session Description of Parameter
841 *@return
842 *@see
843 */
844 public HObject e2ComArg(HComplex c0, HComplex c1, Session session) {
845 return c0.multiply(c1);
846 }
847
848
849 /**
850 * Method Declaration.
851 *
852 *@param fun
853 *@param session Description of Parameter
854 *@return
855 *@see
856 */
857 public String toOpString(HFunction fun, Session session) {
858 final int prec = C.MULTIPLY_PRECEDENCE;
859 final char ch = '*';
860 StringBuffer buf = new StringBuffer();
861 HObject temp;
862
863 if (fun.size() <= 1) {
864 // important for tracing pattern-matching
865 buf.append("Multiply(");
866
867 if (fun.size() == 1) {
868 // buf.append(fun.get(0).toString());
869 fun.get(0).toStringBuffer(buf, session);
870 }
871
872 buf.append(")");
873
874 return buf.toString();
875 }
876
877 for (int i = 0; i < fun.size(); i++) {
878 temp = fun.get(i);
879
880 if (temp.equals(C.CN1)) {
881 buf.append('-');
882 }
883 else {
884 if (temp.precedence() < prec) {
885 buf.append('(');
886 }
887
888 //buf.append(temp.toString());
889 temp.toStringBuffer(buf, session);
890
891 if (temp.precedence() < prec) {
892 buf.append(')');
893 }
894
895 if (i != (fun.size() - 1)) {
896 buf.append(ch);
897 }
898 }
899 }
900
901 return buf.toString();
902 }
903
904
905 /**
906 * Method Declaration.
907 *
908 *@return
909 *@see
910 */
911 public int precedence() {
912 return C.MULTIPLY_PRECEDENCE;
913 }
914
915 }
916
917 /**
918 * Class Declaration.
919 *
920 *@author Klaus Hartlage <A HREF="mailto:khartlage@t-online.de">
921 * khartlage@t-online.de</A>
922 *@created 16. Juli 2001
923 *@see
924 *@version %I%, %G%
925 */
926 class EPow extends E2SArg implements FunctionOpEvaluator {
927
928
929 /**
930 * Method Declaration.
931 *
932 *@param o0
933 *@param o1
934 *@param session Description of Parameter
935 *@return
936 *@see
937 */
938 public HObject e2ObjArg(HObject o0, HObject o1, Session session) {
939 if ((o0 instanceof HMultinomial) && (o1 instanceof HInteger)) {
940 return ((HMultinomial) o0).pow((HInteger) o1);
941 }
942 if (o0 instanceof HDomainInstance && o1 instanceof HInteger) {
943 return ObjectD.binaryCall("pow", ((HDomainInstance) o0),
944 ((HInteger) o1));
945 }
946 // Context ct = ((ContextThread) Thread.currentThread()).getContext();
947 if (session.getNumericFlag()) {
948 if (o0.equals(C.CD0)) {
949 if (o1.equals(C.CD0)) {
950 // 0^0
951 throw new HThrowException(C.UndefinedError, C.Pow,
952 new HString("0^0"));
953 }
954
955 if (o1 instanceof HSignedNumber &&
956 ((HSignedNumber) o1).isNegative()) {
957 throw new HThrowException(C.ArithmeticError, C.Pow,
958 new HString("division by zero"));
959 }
960
961 return C.CD0;
962 }
963
964 if (o1.equals(C.CD0)) {
965 return C.CD1;
966 }
967
968 if (o1.equals(C.CD1)) {
969 return o0;
970 }
971
972 if (o0.equals(C.CD1)) {
973 return C.CD1;
974 }
975 }
976 if (o0.equals(C.C0)) {
977 if (o1.equals(C.C0)) {
978 // 0^0
979 throw new HThrowException(C.UndefinedError, C.Pow,
980 new HString("0^0"));
981 }
982
983 if (o1 instanceof HSignedNumber &&
984 ((HSignedNumber) o1).isNegative()) {
985 throw new HThrowException(C.ArithmeticError, C.Pow,
986 new HString("division by zero"));
987 }
988
989 return C.C0;
990 }
991
992 if (o1.equals(C.C0)) {
993 return C.C1;
994 }
995
996 if (o1.equals(C.C1)) {
997 return o0;
998 }
999
1000 if (o0.equals(C.C1)) {
1001 return C.C1;
1002 }
1003
1004 if (o1.isNumber() && o0.head().equals(C.Pow)) {
1005 HFunction f0 = (HFunction) o0;
1006
1007 if ((f0.size() == 2) && f0.get(1).isNumber()) {
1008 return C.Pow.f(f0.get(0), C.Multiply.f(f0.get(1), o1));
1009 }
1010 }
1011 /*
1012 * if (o0.head().equals(C.Multiply) && o1.isNumber()) {
1013 * HFunction f0 = (HFunction) o0;
1014 * if ((f0.size() > 0) && f0.get(0).isNumber()) {
1015 * return C.Multiply.f(C.Pow.f(f0.get(0), o1),
1016 * C.Pow.f(
1017 * new HFunction(f0, C.Multiply, 1, f0.size(), true), o1));
1018 * }
1019 * }
1020 */
1021 if (o0.head().equals(C.Multiply)) {
1022 if (o1 instanceof HInteger) {
1023 // (a * b * c)^n => a^n * b^n * c^n
1024 HFunction f0 = (HFunction) o0;
1025 HFunction result = C.Multiply.f();
1026 for (int i = 0; i < f0.size(); i++) {
1027 result.add(C.Pow.f(f0.get(i), o1));
1028 }
1029 return result;
1030 }
1031 if (o1.isNumber()) {
1032 HFunction f0 = (HFunction) o0;
1033
1034 if ((f0.size() > 0) && f0.get(0).isNumber()) {
1035 return C.Multiply.f(C.Pow.f(f0.get(0), o1),
1036 C.Pow.f(
1037 new HFunction(f0, C.Multiply, 1, f0.size(), true), o1));
1038 }
1039 }
1040 }
1041 return null;
1042 }
1043
1044
1045 /**
1046 * Method Declaration.
1047 *
1048 *@param i0
1049 *@param i1
1050 *@param session Description of Parameter
1051 *@return
1052 *@see
1053 */
1054 public HObject e2IntArg(HInteger i0, HInteger i1, Session session) {
1055 if (i0.equals(C.C0)) {
1056 // all other cases see e2ObjArg
1057 return null;
1058 }
1059
1060 if (i1.less(session, C.C0)) {
1061 return new HFraction(C.C1, i0.pow(i1.negate().intValue()));
1062 }
1063
1064 return i0.pow(i1.intValue());
1065 }
1066
1067
1068 /**
1069 * Method Declaration.
1070 *
1071 *@param f0
1072 *@param f1
1073 *@param session Description of Parameter
1074 *@return
1075 *@see
1076 */
1077 public HObject e2FraArg(HFraction f0, HFraction f1, Session session) {
1078 if (f0.numer().equals(C.C0)) {
1079 return C.C0;
1080 }
1081
1082 if (f1.numer().equals(C.C0)) {
1083 return C.C1;
1084 }
1085
1086 // if (f0.denom().equals(C.C1) && f1.numer().equals(C.C1)) { // example: (-27)^(1/3) or 8^(1/3)
1087 if (f1.numer().equals(C.C1)) {
1088 HInteger a = f0.numer();
1089 HInteger b = f0.denom();
1090
1091 if (f1.isNegative()) {
1092 return null;
1093 }
1094 final HInteger root = f1.denom();
1095
1096 HObject new_numer = calculateRoot(a, root, session);
1097 HObject new_denom = calculateRoot(b, root, session);
1098
1099 if (new_numer != null) {
1100 if (new_denom != null) {
1101 return session.EV(C.Multiply.f(new_numer, C.Pow.f(new_denom, C.CN1)));
1102 }
1103 else {
1104 if (a.equals(C.C1)) {
1105 return null;
1106 }
1107 return session.EV(C.Multiply.f(new_numer, C.Pow.f(new HFraction(C.C1, b), f1)));
1108 }
1109 }
1110 else {
1111 if (new_denom != null) {
1112 if (b.equals(C.C1)) {
1113 return null;
1114 }
1115 return session.EV(C.Multiply.f(C.Pow.f(a, f1), C.Pow.f(new_denom, C.CN1)));
1116 }
1117 }
1118 return null;
1119 }
1120
1121 if (f1.denom().unequals(C.C1)) {
1122 return null;
1123 }
1124
1125 int iNumer;
1126 try {
1127 iNumer = f1.numer().getIntValue();
1128 }
1129 catch (IndexOutOfBoundsException iob) {
1130 return null;
1131 }
1132 return f0.pow(iNumer);
1133 }
1134
1135
1136 /**
1137 * Method Declaration.
1138 *
1139 *@param c0
1140 *@param i1
1141 *@param session Description of Parameter
1142 *@return
1143 *@see
1144 */
1145 public HObject eComIntArg(HComplex c0, HInteger i1, Session session) {
1146 if (c0.isZero()) {
1147 return C.C0;
1148 }
1149
1150 if (i1.isZero()) {
1151 return C.C1;
1152 }
1153
1154 return c0.pow(i1.intValue());
1155 }
1156
1157
1158 /**
1159 * Description of the Method
1160 *
1161 *@param d0 Description of Parameter
1162 *@param d1 Description of Parameter
1163 *@param session Description of Parameter
1164 *@return Description of the Returned Value
1165 */
1166 public HObject e2DblArg(HDouble d0, HDouble d1, Session session) {
1167 HDouble res = d0.pow(d1);
1168
1169 if (res.isNaN()) {
1170 return new HDoubleComplex(d0.doubleValue()).pow(
1171 new HDoubleComplex(d1));
1172 }
1173
1174 return res;
1175 }
1176
1177
1178 /**
1179 * Method Declaration.
1180 *
1181 *@param d0
1182 *@param d1
1183 *@param session Description of Parameter
1184 *@return
1185 *@see
1186 */
1187 public HObject e2DblComArg(HDoubleComplex d0, HDoubleComplex d1, Session session) {
1188 return d0.pow(d1);
1189 }
1190
1191
1192 /**
1193 * Description of the Method
1194 *
1195 *@param c0 Description of Parameter
1196 *@param c1 Description of Parameter
1197 *@param session Description of Parameter
1198 *@return Description of the Returned Value
1199 */
1200 public HObject e2ComArg(HComplex c0, HComplex c1, Session session) {
1201 return null;
1202 }
1203
1204
1205 /**
1206 * Method Declaration.
1207 *
1208 *@param fun
1209 *@param session Description of Parameter
1210 *@return
1211 *@see
1212 */
1213 public String toOpString(HFunction fun, Session session) {
1214 StringBuffer buf = new StringBuffer();
1215 HObject temp;
1216
1217 if (fun.size() > 0) {
1218 if ((fun.size() == 2) &&
1219 (fun.get(1).equals(C.CN1) ||
1220 fun.get(1).equals(C.CDN1) ||
1221 fun.get(1).equals(C.C1D2) ||
1222 fun.get(1).equals(C.CN1D2))) {
1223 temp = fun.get(0);
1224
1225 if (fun.get(1).equals(C.C1D2)) {
1226 buf.append("Sqrt(");
1227 temp.toStringBuffer(buf, session);
1228 buf.append(")");
1229 }
1230 else {
1231 buf.append("1/");
1232
1233 if (fun.get(1).equals(C.CN1D2)) {
1234 buf.append("Sqrt(");
1235 temp.toStringBuffer(buf, session);
1236 buf.append(")");
1237 }
1238 else {
1239 if (temp.precedence() < C.MULTIPLY_PRECEDENCE) {
1240 buf.append('(');
1241 }
1242
1243 //buf.append(temp.toString());
1244 temp.toStringBuffer(buf, session);
1245
1246 if (temp.precedence() < C.MULTIPLY_PRECEDENCE) {
1247 buf.append(')');
1248 }
1249 }
1250 }
1251 }
1252 else {
1253 temp = fun.get(0);
1254
1255 if (temp.precedence() < C.POW_PRECEDENCE) {
1256 buf.append('(');
1257 }
1258
1259 //buf.append(temp.toString());
1260 temp.toStringBuffer(buf, session);
1261
1262 if (temp.precedence() < C.POW_PRECEDENCE) {
1263 buf.append(')');
1264 }
1265
1266 if (fun.size() > 1) {
1267 buf.append('^');
1268 }
1269
1270 for (int i = 1; i < fun.size(); i++) {
1271 temp = fun.get(i);
1272
1273 if (temp.precedence() <= C.POW_PRECEDENCE) {
1274 buf.append('(');
1275 }
1276
1277 //buf.append(temp.toString());
1278 temp.toStringBuffer(buf, session);
1279
1280 if (temp.precedence() <= C.POW_PRECEDENCE) {
1281 buf.append(')');
1282 }
1283
1284 if (i != (fun.size() - 1)) {
1285 buf.append('^');
1286 }
1287 }
1288 }
1289 }
1290
1291 return buf.toString();
1292 }
1293
1294
1295 /**
1296 * Method Declaration.
1297 *
1298 *@return
1299 *@see
1300 */
1301 public int precedence() {
1302 return C.POW_PRECEDENCE;
1303 }
1304
1305
1306 /**
1307 * Description of the Method
1308 *
1309 *@param a Description of Parameter
1310 *@param root Description of Parameter
1311 *@param session Description of Parameter
1312 *@return Description of the Returned Value
1313 */
1314 HObject calculateRoot(HInteger a, HInteger root, Session session) {
1315 boolean negFlag = false;
1316 HInteger result;
1317
1318 int iRoot;
1319 try {
1320 iRoot = root.getIntValue();
1321 }
1322 catch (IndexOutOfBoundsException iob) {
1323 return null;
1324 }
1325
1326 if (a.isNegative()) {
1327 if (root.isEven()) {
1328 // complex root ???
1329 a = a.negate();
1330 result = a.root(iRoot);
1331
1332 if (result.pow(iRoot).equals(a)) {
1333 if (iRoot % 4 != 0) {
1334 return session.EV(C.Multiply.f(C.CI, result));
1335 }
1336 }
1337
1338 return null;
1339 }
1340
1341 negFlag = true;
1342 a = a.negate();
1343
1344 }
1345
1346 result = a.root(iRoot);
1347
1348 if (result.pow(iRoot).equals(a)) {
1349 if (negFlag) {
1350 return result.negate();
1351 }
1352 return result;
1353 }
1354
1355 return null;
1356 }
1357
1358}
1359
1360/**
1361 * Class Declaration.
1362 *
1363 *@author Klaus Hartlage <A HREF="mailto:khartlage@t-online.de">
1364 * khartlage@t-online.de</A>
1365 *@created 16. Juli 2001
1366 *@see
1367 *@version %I%, %G%
1368 */
1369class ESqrt extends E1Arg {
1370
1371
1372 /**
1373 * Method Declaration.
1374 *
1375 *@param o
1376 *@return
1377 *@see
1378 */
1379 public HObject e1ObjArg(HObject o) {
1380 return C.Pow.f(o, C.C1D2);
1381 }
1382
1383}
1384
1385
1386class EReplaceAll extends SFunctionEvaluator implements FunctionOpEvaluator {
1387 /**
1388 * Constructor for the EReplaceAll object
1389 */
1390 public EReplaceAll() {
1391 }
1392
1393
1394 /**
1395 *@param vect the function, which should be evaluated
1396 *@param session Description of Parameter
1397 *@return <code>null</code> or the evaluated object
1398 */
1399 public HObject evaluate(HFunction vect, Session session) {
1400 if (vect.size() == 2 && vect.get(1) instanceof HFunction) {
1401 HFunction f = (HFunction) vect.get(1);
1402 HObject a0 = vect.get(0);
1403
1404 if (f.isList()) {
1405 for (int i = 0; i < f.size(); i++) {
1406 if (f.get(i) instanceof HFunction) {
1407 a0 = useRule(a0, (HFunction) f.get(i), session);
1408 }
1409 }
1410
1411 return a0;
1412 }
1413 else {
1414 return useRule(a0, f, session);
1415 }
1416 }
1417
1418 return null;
1419 }
1420
1421
1422 /**
1423 * Method Declaration.
1424 *
1425 *@param fun
1426 *@param session Description of Parameter
1427 *@return
1428 *@see
1429 */
1430 public String toOpString(HFunction fun, Session session) {
1431 return E2SArg.operatorString(fun, "/.", C.REPLACEALL_PRECEDENCE, session);
1432 }
1433
1434
1435 /**
1436 * Method Declaration.
1437 *
1438 *@return
1439 *@see
1440 */
1441 public int precedence() {
1442 return C.REPLACEALL_PRECEDENCE;
1443 }
1444
1445
1446 /**
1447 * Method Declaration.
1448 *
1449 *@param a0
1450 *@param f
1451 *@param session Description of Parameter
1452 *@return
1453 *@see
1454 */
1455 HObject useRule(HObject a0, HFunction f, Session session) {
1456 HObject result;
1457 HRuleSet rset;
1458
1459 if (f.size() == 2 && (f.head() == C.Rule || f.head() == C.RuleDelayed)) {
1460 rset = new HRuleSet(f.get(0).head());
1461
1462 if (f.head() == C.Rule) {
1463 rset.putDownRule(session, HRule.RULE, f.get(0), f.get(1));
1464 }
1465 else {
1466 rset.putDownRule(session, HRule.RULEDELAYED, f.get(0),
1467 f.get(1));
1468 }
1469
1470 result = rset.getDownRule(a0, session);
1471
1472 if (result != null) {
1473 return result;
1474 }
1475
1476 if (a0 instanceof HFunction) {
1477 result = ((HFunction) a0).replaceAll(rset, session);
1478
1479 if (result != null) {
1480 return result;
1481 }
1482 }
1483 }
1484
1485 return a0;
1486 }
1487
1488}
1489
1490class ERule extends SFunctionEvaluator implements FunctionOpEvaluator {
1491
1492
1493 /**
1494 * Constructor for the ERule object
1495 */
1496 public ERule() {
1497 }
1498
1499
1500 /**
1501 *@param vect the function, which should be evaluated
1502 *@param session Description of Parameter
1503 *@return <code>null</code> or the evaluated object
1504 */
1505 public HObject evaluate(HFunction vect, Session session) {
1506 if (vect.size() == 2) {
1507 HObject a0 = (HObject) vect.get(0);
1508 HObject arg2 = session.ELoop((HObject) vect.get(1));
1509
1510 if (a0 instanceof HSymbol) {
1511 if (arg2 == null) {
1512 return null;
1513 }
1514
1515 return C.Rule.f(a0, arg2);
1516 }
1517
1518 if (a0 instanceof HFunction) {
1519 HObject result = ((HFunction) a0).evaluateArgAttr(session);
1520
1521 if (result != null) {
1522 a0 = result;
1523
1524 if (arg2 == null) {
1525 arg2 = vect.get(1);
1526 }
1527 }
1528 else {
1529 if (arg2 == null) {
1530 return null;
1531 }
1532 }
1533
1534 return C.Rule.f(a0, arg2);
1535 }
1536 }
1537
1538 return null;
1539 }
1540
1541
1542 /**
1543 * Method Declaration.
1544 *
1545 *@param fun
1546 *@param session Description of Parameter
1547 *@return
1548 *@see
1549 */
1550 public String toOpString(HFunction fun, Session session) {
1551 return E2SArg.operatorString(fun, "->", C.RULE_PRECEDENCE, session);
1552 }
1553
1554
1555 /**
1556 * Method Declaration.
1557 *
1558 *@return
1559 *@see
1560 */
1561 public int precedence() {
1562 return C.RULE_PRECEDENCE;
1563 }
1564
1565}
1566
1567/**
1568 * Description of the Class
1569 *
1570 *@author khartlage
1571 *@created 8. Oktober 2001
1572 */
1573class ERuleDelayed extends SFunctionEvaluator implements FunctionOpEvaluator {
1574
1575
1576 /**
1577 * Constructor for the ERuleDelayed object
1578 */
1579 public ERuleDelayed() {
1580 }
1581
1582
1583 /**
1584 *@param vect the function, which should be evaluated
1585 *@param session Description of Parameter
1586 *@return <code>null</code> or the evaluated object
1587 */
1588 public HObject evaluate(HFunction vect, Session session) {
1589 if (vect.size() == 2) {
1590 HObject a0 = (HObject) vect.get(0);
1591 HObject arg2 = (HObject) vect.get(1);
1592
1593 if (a0 instanceof HSymbol) {
1594 return C.Rule.f(a0, arg2);
1595 }
1596
1597 if (a0 instanceof HFunction) {
1598 HObject result = ((HFunction) a0).evaluateArgAttr(session);
1599
1600 if (result != null) {
1601 a0 = result;
1602 }
1603
1604 return C.Rule.f(a0, arg2);
1605 }
1606 }
1607
1608 return null;
1609 }
1610
1611
1612 /**
1613 * Method Declaration.
1614 *
1615 *@param fun
1616 *@param session Description of Parameter
1617 *@return
1618 *@see
1619 */
1620 public String toOpString(HFunction fun, Session session) {
1621 return E2SArg.operatorString(fun, ":>", C.RULEDELAYED_PRECEDENCE, session);
1622 }
1623
1624
1625 /**
1626 * Method D