1 /*
2 Qalculate (library)
3
4 Copyright (C) 2003-2007, 2008, 2016-2021 Hanna Knutsson (hanna.knutsson@protonmail.com)
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 */
11
12 #include "support.h"
13
14 #include "MathStructure.h"
15 #include "Calculator.h"
16 #include "BuiltinFunctions.h"
17 #include "Number.h"
18 #include "Function.h"
19 #include "Variable.h"
20 #include "Unit.h"
21 #include "Prefix.h"
22 #include "MathStructure-support.h"
23
24 using std::string;
25 using std::cout;
26 using std::vector;
27 using std::endl;
28
warn_test_interval(MathStructure & mnonzero,const EvaluationOptions & eo2)29 bool warn_test_interval(MathStructure &mnonzero, const EvaluationOptions &eo2) {
30 if(mnonzero.isComparison() && mnonzero[0].isVariable() && !mnonzero[0].variable()->isKnown() && !((UnknownVariable*) mnonzero[0].variable())->interval().isUndefined()) {
31 /*if(((UnknownVariable*) mnonzero[0].variable())->interval().isNumber() && mnonzero[1].isNumber()) {
32 MathStructure mbak(mnonzero);
33 mnonzero[0] = ((UnknownVariable*) mnonzero[0].variable())->interval();
34 mnonzero.eval(eo2);
35 if(!mnonzero.isNumber()) mnonzero.clear();
36 return true;
37 } else*/ if(((UnknownVariable*) mnonzero[0].variable())->interval().containsInterval(true)) {
38 MathStructure mbak(mnonzero);
39 mnonzero[0] = ((UnknownVariable*) mnonzero[0].variable())->interval();
40 mnonzero.eval(eo2);
41 if(mnonzero.isComparison()) mnonzero = mbak;
42 else return true;
43 } else {
44 mnonzero[0] = ((UnknownVariable*) mnonzero[0].variable())->interval();
45 mnonzero.eval(eo2);
46 return true;
47 }
48 } else if(mnonzero.isLogicalAnd() || mnonzero.isLogicalOr()) {
49 bool b_ret = false;
50 for(size_t i = 0; i < mnonzero.size(); i++) {
51 if(warn_test_interval(mnonzero[i], eo2)) b_ret = true;
52 }
53 if(b_ret) {
54 mnonzero.calculatesub(eo2, eo2, false);
55 return true;
56 }
57 }
58 return false;
59 }
warn_about_assumed_not_value(const MathStructure & mstruct,const MathStructure & mvalue,const EvaluationOptions & eo)60 bool warn_about_assumed_not_value(const MathStructure &mstruct, const MathStructure &mvalue, const EvaluationOptions &eo) {
61 CALCULATOR->beginTemporaryStopMessages();
62 EvaluationOptions eo2 = eo;
63 eo2.assume_denominators_nonzero = false;
64 eo2.test_comparisons = true;
65 eo2.isolate_x = true;
66 eo2.expand = true;
67 eo2.approximation = APPROXIMATION_APPROXIMATE;
68 MathStructure mnonzero(mstruct);
69 mnonzero.add(mvalue, OPERATION_NOT_EQUALS);
70 mnonzero.eval(eo2);
71 warn_test_interval(mnonzero, eo2);
72 if(CALCULATOR->endTemporaryStopMessages()) return false;
73 if(mnonzero.isZero()) return false;
74 if(mnonzero.isOne()) return true;
75 if(mvalue.isZero() && mnonzero.isComparison() && mnonzero.comparisonType() == COMPARISON_NOT_EQUALS && mnonzero[1].isZero() && mnonzero[0].representsApproximatelyZero(true)) return false;
76 CALCULATOR->error(false, _("Required assumption: %s."), format_and_print(mnonzero).c_str(), NULL);
77 return true;
78 }
warn_about_denominators_assumed_nonzero(const MathStructure & mstruct,const EvaluationOptions & eo)79 bool warn_about_denominators_assumed_nonzero(const MathStructure &mstruct, const EvaluationOptions &eo) {
80 CALCULATOR->beginTemporaryStopMessages();
81 EvaluationOptions eo2 = eo;
82 eo2.assume_denominators_nonzero = false;
83 eo2.test_comparisons = true;
84 eo2.isolate_x = true;
85 eo2.expand = true;
86 eo2.approximation = APPROXIMATION_APPROXIMATE;
87 MathStructure mnonzero(mstruct);
88 mnonzero.add(m_zero, OPERATION_NOT_EQUALS);
89 mnonzero.eval(eo2);
90 warn_test_interval(mnonzero, eo2);
91 if(CALCULATOR->endTemporaryStopMessages()) return false;
92 if(mnonzero.isZero()) return false;
93 if(mnonzero.isOne()) return true;
94 if(mnonzero.isComparison() && mnonzero.comparisonType() == COMPARISON_NOT_EQUALS && mnonzero[1].isZero() && mnonzero[0].representsApproximatelyZero(true)) return false;
95 CALCULATOR->error(false, _("To avoid division by zero, the following must be true: %s."), format_and_print(mnonzero).c_str(), NULL);
96 return true;
97 }
warn_about_denominators_assumed_nonzero_or_positive(const MathStructure & mstruct,const MathStructure & mstruct2,const EvaluationOptions & eo)98 bool warn_about_denominators_assumed_nonzero_or_positive(const MathStructure &mstruct, const MathStructure &mstruct2, const EvaluationOptions &eo) {
99 CALCULATOR->beginTemporaryStopMessages();
100 EvaluationOptions eo2 = eo;
101 eo2.assume_denominators_nonzero = false;
102 eo2.test_comparisons = true;
103 eo2.isolate_x = true;
104 eo2.expand = true;
105 eo2.approximation = APPROXIMATION_APPROXIMATE;
106 MathStructure mnonzero(mstruct);
107 mnonzero.add(m_zero, OPERATION_NOT_EQUALS);
108 MathStructure *mpos = new MathStructure(mstruct2);
109 mpos->add(m_zero, OPERATION_EQUALS_GREATER);
110 mnonzero.add_nocopy(mpos, OPERATION_LOGICAL_OR);
111 mnonzero.eval(eo2);
112 warn_test_interval(mnonzero, eo2);
113 if(CALCULATOR->endTemporaryStopMessages()) return false;
114 if(mnonzero.isZero()) return false;
115 if(mnonzero.isOne()) return true;
116 if(mnonzero.isComparison() && mnonzero.comparisonType() == COMPARISON_NOT_EQUALS && mnonzero[1].isZero() && mnonzero[0].representsApproximatelyZero(true)) return false;
117 CALCULATOR->error(false, _("To avoid division by zero, the following must be true: %s."), format_and_print(mnonzero).c_str(), NULL);
118 return true;
119 }
warn_about_denominators_assumed_nonzero_llgg(const MathStructure & mstruct,const MathStructure & mstruct2,const MathStructure & mstruct3,const EvaluationOptions & eo)120 bool warn_about_denominators_assumed_nonzero_llgg(const MathStructure &mstruct, const MathStructure &mstruct2, const MathStructure &mstruct3, const EvaluationOptions &eo) {
121 CALCULATOR->beginTemporaryStopMessages();
122 EvaluationOptions eo2 = eo;
123 eo2.assume_denominators_nonzero = false;
124 eo2.test_comparisons = true;
125 eo2.isolate_x = true;
126 eo2.expand = true;
127 eo2.approximation = APPROXIMATION_APPROXIMATE;
128 MathStructure mnonzero(mstruct);
129 mnonzero.add(m_zero, OPERATION_NOT_EQUALS);
130 MathStructure *mpos = new MathStructure(mstruct2);
131 mpos->add(m_zero, OPERATION_EQUALS_GREATER);
132 MathStructure *mpos2 = new MathStructure(mstruct3);
133 mpos2->add(m_zero, OPERATION_EQUALS_GREATER);
134 mpos->add_nocopy(mpos2, OPERATION_LOGICAL_AND);
135 mnonzero.add_nocopy(mpos, OPERATION_LOGICAL_OR);
136 MathStructure *mneg = new MathStructure(mstruct2);
137 mneg->add(m_zero, OPERATION_LESS);
138 MathStructure *mneg2 = new MathStructure(mstruct3);
139 mneg2->add(m_zero, OPERATION_LESS);
140 mneg->add_nocopy(mneg2, OPERATION_LOGICAL_AND);
141 mnonzero.add_nocopy(mneg, OPERATION_LOGICAL_OR);
142 mnonzero.eval(eo2);
143 warn_test_interval(mnonzero, eo2);
144 if(CALCULATOR->endTemporaryStopMessages()) return false;
145 if(mnonzero.isZero()) return false;
146 if(mnonzero.isOne()) return true;
147 if(mnonzero.isComparison() && mnonzero.comparisonType() == COMPARISON_NOT_EQUALS && mnonzero[1].isZero() && mnonzero[0].representsApproximatelyZero(true)) return false;
148 CALCULATOR->error(false, _("To avoid division by zero, the following must be true: %s."), format_and_print(mnonzero).c_str(), NULL);
149 return true;
150 }
151
merge_addition(MathStructure & mstruct,const EvaluationOptions & eo,MathStructure * mparent,size_t index_this,size_t index_mstruct,bool reversed)152 int MathStructure::merge_addition(MathStructure &mstruct, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this, size_t index_mstruct, bool reversed) {
153 // test if two terms can be merged
154 if(mstruct.type() == STRUCT_NUMBER && m_type == STRUCT_NUMBER) {
155 // both terms are numbers try Number::add() (might never fail for infinite values)
156 Number nr(o_number);
157 if(nr.add(mstruct.number()) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || mstruct.number().isApproximate())) {
158 if(o_number == nr) {
159 o_number = nr;
160 numberUpdated();
161 return 2;
162 }
163 o_number = nr;
164 numberUpdated();
165 return 1;
166 }
167 return -1;
168 }
169 if(isZero()) {
170 // 0+a=a
171 if(mparent) {
172 mparent->swapChildren(index_this + 1, index_mstruct + 1);
173 } else {
174 set_nocopy(mstruct, true);
175 }
176 return 3;
177 }
178 if(mstruct.isZero()) {
179 // a+0=a
180 MERGE_APPROX_AND_PREC(mstruct)
181 return 2;
182 }
183 if(m_type == STRUCT_NUMBER && o_number.isInfinite()) {
184 if(mstruct.representsReal(false)) {
185 // infinity+a=infinity
186 MERGE_APPROX_AND_PREC(mstruct)
187 return 2;
188 }
189 } else if(mstruct.isNumber() && mstruct.number().isInfinite()) {
190 if(representsReal(false)) {
191 // a+infinity=infinity
192 if(mparent) {
193 mparent->swapChildren(index_this + 1, index_mstruct + 1);
194 } else {
195 clear(true);
196 o_number = mstruct.number();
197 MERGE_APPROX_AND_PREC(mstruct)
198 }
199 return 3;
200 }
201 }
202 if(representsUndefined() || mstruct.representsUndefined()) return -1;
203 switch(m_type) {
204 case STRUCT_VECTOR: {
205 switch(mstruct.type()) {
206 case STRUCT_ADDITION: {
207 // try again with reversed order
208 return 0;
209 }
210 case STRUCT_VECTOR: {
211 if(SIZE == mstruct.size()) {
212 // [a1,a2,a3,...]+[b1,b2,b3,...]=[a1+b1,a2+b2,a3+b3,...]
213 for(size_t i = 0; i < SIZE; i++) {
214 CHILD(i).calculateAdd(mstruct[i], eo, this, i);
215 }
216 MERGE_APPROX_AND_PREC(mstruct)
217 CHILDREN_UPDATED
218 return 1;
219 }
220 }
221 default: {
222 if(mstruct.representsScalar()) {
223 // [a1,a2,a3,...]+b=[a1+b,a2+b,a3+b,...]
224 for(size_t i = 0; i < SIZE; i++) {
225 CHILD(i).calculateAdd(mstruct, eo, this, i);
226 }
227 CHILDREN_UPDATED
228 return 1;
229 }
230 return -1;
231 }
232 }
233 return -1;
234 }
235 case STRUCT_ADDITION: {
236 switch(mstruct.type()) {
237 case STRUCT_ADDITION: {
238 // (a1+a2+a3+...)+(b1+b2+b3+...)=a1+a2+a3+...+b1+b2+b3+...
239 for(size_t i = 0; i < mstruct.size(); i++) {
240 if(reversed) {
241 INSERT_REF(&mstruct[i], i)
242 calculateAddIndex(i, eo, false);
243 } else {
244 APPEND_REF(&mstruct[i]);
245 calculateAddLast(eo, false);
246 }
247 }
248 MERGE_APPROX_AND_PREC(mstruct)
249 if(SIZE == 1) {
250 setToChild(1, false, mparent, index_this + 1);
251 } else if(SIZE == 0) {
252 clear(true);
253 } else {
254 evalSort();
255 }
256 return 1;
257 }
258 default: {
259 // (a1+a2+a3+...)+b=a1+a2+a3+...+b
260 MERGE_APPROX_AND_PREC(mstruct)
261 if(reversed) {
262 PREPEND_REF(&mstruct);
263 calculateAddIndex(0, eo, true, mparent, index_this);
264 } else {
265 APPEND_REF(&mstruct);
266 calculateAddLast(eo, true, mparent, index_this);
267 }
268 return 1;
269 }
270 }
271 break;
272 }
273 case STRUCT_MULTIPLICATION: {
274 switch(mstruct.type()) {
275 case STRUCT_VECTOR: {}
276 case STRUCT_ADDITION: {
277 // try again with reversed order
278 return 0;
279 }
280 case STRUCT_MULTIPLICATION: {
281 size_t i1 = 0, i2 = 0;
282 bool b = true;
283 if(CHILD(0).isNumber()) i1 = 1;
284 if(mstruct[0].isNumber()) i2 = 1;
285 if(SIZE - i1 == mstruct.size() - i2) {
286 for(size_t i = i1; i < SIZE; i++) {
287 if(CHILD(i) != mstruct[i + i2 - i1]) {
288 b = false;
289 break;
290 }
291 }
292 if(b) {
293 // ax+bx=(a+b)x, axy+xy=(a+1)xy, xy+xy=2xy (when a and b are numbers)
294 if(i1 == 0) {
295 PREPEND(m_one);
296 }
297 if(i2 == 0) {
298 CHILD(0).number()++;
299 } else {
300 if(!CHILD(0).number().add(mstruct[0].number())) return -1;
301 }
302 MERGE_APPROX_AND_PREC(mstruct)
303 calculateMultiplyIndex(0, eo, true, mparent, index_this);
304 return 1;
305 }
306 }
307
308 for(size_t i2 = 0; i2 < SIZE; i2++) {
309 if(eo.transform_trigonometric_functions && CHILD(i2).isPower() && CHILD(i2)[0].isFunction() && (CHILD(i2)[0].function()->id() == FUNCTION_ID_COS || CHILD(i2)[0].function()->id() == FUNCTION_ID_SIN) && CHILD(i2)[0].size() == 1 && CHILD(i2)[1].isNumber() && CHILD(i2)[1].number().isTwo() && mstruct.size() > 0) {
310 if(!FUNCTION_PROTECTED(eo, CHILD(i2)[0].function()->id() == FUNCTION_ID_SIN ? FUNCTION_ID_COS : FUNCTION_ID_SIN)) {
311 for(size_t i = 0; i < mstruct.size(); i++) {
312 if(mstruct[i].isPower() && mstruct[i][0].isFunction() && mstruct[i][0].function()->id() == (CHILD(i2)[0].function()->id() == FUNCTION_ID_SIN ? FUNCTION_ID_COS : FUNCTION_ID_SIN) && mstruct[i][0].size() == 1 && mstruct[i][1].isNumber() && mstruct[i][1].number().isTwo() && CHILD(i2)[0][0] == mstruct[i][0][0]) {
313 // a*sin(x)^2+b*cos(x)^2=(a-b)*sin(x)^2+b
314 MathStructure madd1(*this);
315 MathStructure madd2(mstruct);
316 MathStructure madd;
317 madd1.delChild(i2 + 1, true);
318 madd2.delChild(i + 1, true);
319 if(CHILD(i2)[0].function()->id() == FUNCTION_ID_SIN) {madd = madd2; madd2.calculateNegate(eo);}
320 else {madd = madd1; madd1.calculateNegate(eo);}
321 if(madd1.calculateAdd(madd2, eo)) {
322 SET_CHILD_MAP(i2);
323 CHILD(0).setFunctionId(FUNCTION_ID_SIN);
324 calculateMultiply(madd1, eo);
325 EvaluationOptions eo2 = eo;
326 eo2.transform_trigonometric_functions = false;
327 calculateAdd(madd, eo2);
328 return 1;
329 }
330 }
331 }
332 }
333 if(eo.protected_function != CHILD(i2)[0].function()) {
334 // ay*sin(x)^2-ay=-ay*cos(x)^2, ay*cos(x)^2-ay=-ay*sin(x)^2
335 bool b = false;
336 if(mstruct[0].isNumber()) {
337 if(CHILD(0).isNumber()) {
338 if(mstruct.size() == SIZE - 1 && CHILD(0).number() == -mstruct[0].number()) {
339 b = true;
340 for(size_t i = 1; i < mstruct.size(); i++) {
341 if(!mstruct[i].equals(CHILD(i2 > i ? i : i + 1))) {b = false; break;}
342 }
343 }
344 } else if(mstruct.size() == SIZE && mstruct[0].isMinusOne()) {
345 b = true;
346 for(size_t i = 1; i < mstruct.size(); i++) {
347 if(!mstruct[i].equals(CHILD(i2 >= i ? i - 1 : i))) {b = false; break;}
348 }
349 }
350 } else if(mstruct.size() == SIZE - 2 && CHILD(0).isMinusOne()) {
351 b = true;
352 for(size_t i = 0; i < mstruct.size(); i++) {
353 if(!mstruct[i].equals(CHILD(i2 - 1 >= i ? i + 1 : i + 2))) {b = false; break;}
354 }
355 }
356 if(b) {
357 CHILD(i2)[0].setFunctionId(CHILD(i2)[0].function()->id() == FUNCTION_ID_COS ? FUNCTION_ID_SIN : FUNCTION_ID_COS);
358 MERGE_APPROX_AND_PREC(mstruct)
359 calculateNegate(eo, mparent, index_this);
360 return 1;
361 }
362 }
363 } else if(eo.transform_trigonometric_functions && CHILD(i2).isPower() && CHILD(i2)[0].isFunction() && (CHILD(i2)[0].function()->id() == FUNCTION_ID_COSH || CHILD(i2)[0].function()->id() == FUNCTION_ID_SINH) && CHILD(i2)[0].size() == 1 && CHILD(i2)[1].isNumber() && CHILD(i2)[1].number().isTwo() && mstruct.size() > 0) {
364 if(!FUNCTION_PROTECTED(eo, CHILD(i2)[0].function()->id() == FUNCTION_ID_SINH ? FUNCTION_ID_COSH : FUNCTION_ID_SINH)) {
365 for(size_t i = 0; i < mstruct.size(); i++) {
366 if(mstruct[i].isPower() && mstruct[i][0].isFunction() && mstruct[i][0].function()->id() == (CHILD(i2)[0].function()->id() == FUNCTION_ID_SINH ? FUNCTION_ID_COSH : FUNCTION_ID_SINH) && mstruct[i][0].size() == 1 && mstruct[i][1].isNumber() && mstruct[i][1].number().isTwo() && CHILD(i2)[0][0] == mstruct[i][0][0]) {
367 // a*sinh(x)^2+b*cosh(x)^2=(a+b)*sinh(x)^2+b
368 MathStructure madd1(*this);
369 MathStructure madd2(mstruct);
370 MathStructure madd;
371 madd1.delChild(i2 + 1, true);
372 madd2.delChild(i + 1, true);
373 if(mstruct[i][0].function()->id() == FUNCTION_ID_SINH) madd = madd1;
374 else madd = madd2;
375 if(madd1.calculateAdd(madd2, eo)) {
376 SET_CHILD_MAP(i2);
377 CHILD(0).setFunctionId(FUNCTION_ID_SINH);
378 calculateMultiply(madd1, eo);
379 EvaluationOptions eo2 = eo;
380 eo2.transform_trigonometric_functions = false;
381 calculateAdd(madd, eo2);
382 return 1;
383 }
384 }
385 }
386 }
387 if(eo.protected_function != CHILD(i2)[0].function()) {
388 if(CHILD(i2)[0].function()->id() == FUNCTION_ID_SINH && mstruct.size() == SIZE - 1) {
389 // ay*sinh(x)^2+ay=ay*cosh(x)^2
390 for(size_t i = 0; i < mstruct.size(); i++) {
391 if(!mstruct[i].equals(CHILD(i2 > i ? i : i + 1))) break;
392 if(i == mstruct.size() - 1) {
393 CHILD(i2)[0].setFunctionId(FUNCTION_ID_COSH);
394 MERGE_APPROX_AND_PREC(mstruct)
395 return 1;
396 }
397 }
398 } else if(CHILD(i2)[0].function()->id() == FUNCTION_ID_COSH) {
399 // ay*cosh(x)^2-ay=ay*sinh(x)^2
400 bool b = false;
401 if(mstruct[0].isNumber()) {
402 if(CHILD(0).isNumber()) {
403 if(mstruct.size() == SIZE - 1 && CHILD(0).number() == -mstruct[0].number()) {
404 b = true;
405 for(size_t i = 1; i < mstruct.size(); i++) {
406 if(!mstruct[i].equals(CHILD(i2 > i ? i : i + 1))) {b = false; break;}
407 }
408 }
409 } else if(mstruct.size() == SIZE && mstruct[0].isMinusOne()) {
410 b = true;
411 for(size_t i = 1; i < mstruct.size(); i++) {
412 if(!mstruct[i].equals(CHILD(i2 >= i ? i - 1 : i))) {b = false; break;}
413 }
414 }
415 } else if(mstruct.size() == SIZE - 2 && CHILD(0).isMinusOne()) {
416 b = true;
417 for(size_t i = 1; i < mstruct.size(); i++) {
418 if(!mstruct[i].equals(CHILD(i2 - 1 >= i ? i + 1 : i + 2))) {b = false; break;}
419 }
420 }
421 if(b) {
422 CHILD(i2)[0].setFunctionId(FUNCTION_ID_SINH);
423 MERGE_APPROX_AND_PREC(mstruct)
424 return 1;
425 }
426 }
427 }
428 } else if(CHILD(i2).isFunction()) {
429 if(CHILD(i2).function()->id() == FUNCTION_ID_SIGNUM && !FUNCTION_PROTECTED(eo, FUNCTION_ID_SIGNUM) && CHILD(i2).size() == 2 && CHILD(i2)[0].isAddition() && CHILD(i2)[0].size() == 2 && CHILD(i2)[0].representsReal(true)) {
430 // x*sgn(x+y)+y*sgn(x+y)=abs(x+y)
431 for(size_t im = 0; im < mstruct.size(); im++) {
432 if(mstruct[im] == CHILD(i2)) {
433 MathStructure m1(*this), m2(mstruct);
434 m1.delChild(i2 + 1, true);
435 m2.delChild(im + 1, true);
436 if((m1 == CHILD(i2)[0][0] && m2 == CHILD(i2)[0][1]) || (m2 == CHILD(i2)[0][0] && m1 == CHILD(i2)[0][1])) {
437 SET_CHILD_MAP(i2)
438 setFunctionId(FUNCTION_ID_ABS);
439 ERASE(1)
440 MERGE_APPROX_AND_PREC(mstruct)
441 return 1;
442 }
443 }
444 }
445 } else if(CHILD(i2).function()->id() == FUNCTION_ID_ASIN || CHILD(i2).function()->id() == FUNCTION_ID_ACOS) {
446 CHILD(i2).setFunctionId(CHILD(i2).function()->id() == FUNCTION_ID_ASIN ? FUNCTION_ID_ACOS : FUNCTION_ID_ASIN);
447 if(equals(mstruct) && !FUNCTION_PROTECTED(eo, FUNCTION_ID_ASIN) && !FUNCTION_PROTECTED(eo, FUNCTION_ID_ACOS)) {
448 // asin(x)+acos(x)=pi/2
449 delChild(i2 + 1, true);
450 switch(eo.parse_options.angle_unit) {
451 case ANGLE_UNIT_DEGREES: {calculateMultiply(Number(90, 1, 0), eo); break;}
452 case ANGLE_UNIT_GRADIANS: {calculateMultiply(Number(100, 1, 0), eo); break;}
453 case ANGLE_UNIT_RADIANS: {calculateMultiply(CALCULATOR->getVariableById(VARIABLE_ID_PI), eo); calculateMultiply(nr_half, eo); break;}
454 default: {calculateMultiply(CALCULATOR->getVariableById(VARIABLE_ID_PI), eo); calculateMultiply(nr_half, eo); if(CALCULATOR->getRadUnit()) {calculateMultiply(CALCULATOR->getRadUnit(), eo);} break;}
455 }
456 MERGE_APPROX_AND_PREC(mstruct)
457 return 1;
458 }
459 CHILD(i2).setFunctionId(CHILD(i2).function()->id() == FUNCTION_ID_ASIN ? FUNCTION_ID_ACOS : FUNCTION_ID_ASIN);
460 } else if(CHILD(i2).function()->id() == FUNCTION_ID_SINH || CHILD(i2).function()->id() == FUNCTION_ID_COSH) {
461 CHILD(i2).setFunctionId(CHILD(i2).function()->id() == FUNCTION_ID_SINH ? FUNCTION_ID_COSH : FUNCTION_ID_SINH);
462 if(equals(mstruct) && !FUNCTION_PROTECTED(eo, FUNCTION_ID_SINH) && !FUNCTION_PROTECTED(eo, FUNCTION_ID_COSH)) {
463 // sinh(x)+cosh(x)=e^x
464 MathStructure *mexp = &CHILD(i2)[0];
465 mexp->ref();
466 delChild(i2 + 1, true);
467 MathStructure *mmul = new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_E));
468 mmul->raise_nocopy(mexp);
469 mmul->calculateRaiseExponent(eo);
470 MERGE_APPROX_AND_PREC(mstruct)
471 multiply_nocopy(mmul);
472 calculateMultiplyLast(eo, true, mparent, index_this);
473 return 1;
474 }
475 CHILD(i2).setFunctionId(CHILD(i2).function()->id() == FUNCTION_ID_SINH ? FUNCTION_ID_COSH : FUNCTION_ID_SINH);
476 }
477 }
478 }
479
480 if(eo.transform_trigonometric_functions) {
481 for(size_t i2 = 0; i2 < mstruct.size(); i2++) {
482 if(mstruct[i2].isPower() && mstruct[i2][0].isFunction() && (mstruct[i2][0].function()->id() == FUNCTION_ID_COS || mstruct[i2][0].function()->id() == FUNCTION_ID_SIN) && mstruct[i2][0].size() == 1 && mstruct[i2][1].isNumber() && mstruct[i2][1].number().isTwo() && SIZE > 0) {
483 // ay*sin(x)^2-ay=-ay*cos(x)^2, ay*cos(x)^2-ay=-ay*sin(x)^2
484 if(eo.protected_function != mstruct[i2][0].function()) {
485 bool b = false;
486 if(CHILD(0).isNumber()) {
487 if(mstruct[0].isNumber()) {
488 if(mstruct.size() - 1 == SIZE && CHILD(0).number() == -mstruct[0].number()) {
489 b = true;
490 for(size_t i = 1; i < SIZE; i++) {
491 if(!CHILD(i).equals(mstruct[i2 > i ? i : i + 1])) {b = false; break;}
492 }
493 }
494 } else if(mstruct.size() == SIZE && CHILD(0).isMinusOne()) {
495 b = true;
496 for(size_t i = 1; i < SIZE; i++) {
497 if(!CHILD(i).equals(mstruct[i2 >= i ? i - 1 : i])) {b = false; break;}
498 }
499 }
500 } else if(mstruct.size() - 2 == SIZE && mstruct[0].isMinusOne()) {
501 b = true;
502 for(size_t i = 0; i < SIZE; i++) {
503 if(!CHILD(i).equals(mstruct[i2 - 1 >= i ? i + 1 : i + 2])) {b = false; break;}
504 }
505 }
506 if(b) {
507 mstruct[i2][0].setFunctionId(mstruct[i2][0].function()->id() == FUNCTION_ID_COS ? FUNCTION_ID_SIN : FUNCTION_ID_COS);
508 mstruct.calculateNegate(eo);
509 if(mparent) mparent->swapChildren(index_this + 1, index_mstruct + 1);
510 else set_nocopy(mstruct, true);
511 return 1;
512 }
513 }
514 } else if(mstruct[i2].isPower() && mstruct[i2][0].isFunction() && (mstruct[i2][0].function()->id() == FUNCTION_ID_COSH || mstruct[i2][0].function()->id() == FUNCTION_ID_SINH) && mstruct[i2][0].size() == 1 && mstruct[i2][1].isNumber() && mstruct[i2][1].number().isTwo() && SIZE > 0) {
515 if(eo.protected_function != mstruct[i2][0].function()) {
516 if(mstruct[i2][0].function()->id() == FUNCTION_ID_SINH && mstruct.size() - 1 == SIZE) {
517 // ay*sinh(x)^2+ay=ay*cosh(x)^2
518 for(size_t i = 0; i < SIZE; i++) {
519 if(!CHILD(i).equals(mstruct[i2 > i ? i : i + 1])) break;
520 if(i == SIZE - 1) {
521 mstruct[i2][0].setFunctionId(FUNCTION_ID_COSH);
522 if(mparent) mparent->swapChildren(index_this + 1, index_mstruct + 1);
523 else set_nocopy(mstruct, true);
524 return 1;
525 }
526 }
527 } else if(mstruct[i2][0].function()->id() == FUNCTION_ID_COSH) {
528 // ay*cosh(x)^2-ay=ay*sinh(x)^2
529 bool b = false;
530 if(CHILD(0).isNumber()) {
531 if(mstruct[0].isNumber()) {
532 if(mstruct.size() - 1 == SIZE && CHILD(0).number() == -mstruct[0].number()) {
533 b = true;
534 for(size_t i = 1; i < SIZE; i++) {
535 if(!CHILD(i).equals(mstruct[i2 > i ? i : i + 1])) {b = false; break;}
536 }
537 }
538 } else if(mstruct.size() == SIZE && CHILD(0).isMinusOne()) {
539 b = true;
540 for(size_t i = 1; i < SIZE; i++) {
541 if(!CHILD(i).equals(mstruct[i2 >= i ? i - 1 : i])) {b = false; break;}
542 }
543 }
544 } else if(mstruct.size() - 2 == SIZE && mstruct[0].isMinusOne()) {
545 b = true;
546 for(size_t i = 1; i < SIZE; i++) {
547 if(!CHILD(i).equals(mstruct[i2 - 1 >= i ? i + 1 : i + 2])) {b = false; break;}
548 }
549 }
550 if(b) {
551 mstruct[i2][0].setFunctionId(FUNCTION_ID_SINH);
552 if(mparent) mparent->swapChildren(index_this + 1, index_mstruct + 1);
553 else set_nocopy(mstruct, true);
554 return 1;
555 }
556 }
557 }
558 }
559 }
560 }
561
562 if(!eo.combine_divisions) break;
563 // y/x+z/x=(y+z)/x (eo.combine_divisions is not used anymore)
564 b = true; size_t divs = 0;
565 for(; b && i1 < SIZE; i1++) {
566 if(CHILD(i1).isPower() && CHILD(i1)[1].hasNegativeSign()) {
567 divs++;
568 b = false;
569 for(; i2 < mstruct.size(); i2++) {
570 if(mstruct[i2].isPower() && mstruct[i2][1].hasNegativeSign()) {
571 if(mstruct[i2] == CHILD(i1)) {
572 b = true;
573 }
574 i2++;
575 break;
576 }
577 }
578 }
579 }
580 if(b && divs > 0) {
581 for(; i2 < mstruct.size(); i2++) {
582 if(mstruct[i2].isPower() && mstruct[i2][1].hasNegativeSign()) {
583 b = false;
584 break;
585 }
586 }
587 }
588 if(b && divs > 0) {
589 if(SIZE - divs == 0) {
590 if(mstruct.size() - divs == 0) {
591 calculateMultiply(nr_two, eo);
592 } else if(mstruct.size() - divs == 1) {
593 PREPEND(m_one);
594 for(size_t i = 0; i < mstruct.size(); i++) {
595 if(!mstruct[i].isPower() || !mstruct[i][1].hasNegativeSign()) {
596 mstruct[i].ref();
597 CHILD(0).add_nocopy(&mstruct[i], true);
598 CHILD(0).calculateAddLast(eo, true, this, 0);
599 break;
600 }
601 }
602 calculateMultiplyIndex(0, eo, true, mparent, index_this);
603 } else {
604 for(size_t i = 0; i < mstruct.size();) {
605 if(mstruct[i].isPower() && mstruct[i][1].hasNegativeSign()) {
606 mstruct.delChild(i + 1);
607 } else {
608 i++;
609 }
610 }
611 PREPEND(m_one);
612 mstruct.ref();
613 CHILD(0).add_nocopy(&mstruct, true);
614 CHILD(0).calculateAddLast(eo, true, this, 0);
615 calculateMultiplyIndex(0, eo, true, mparent, index_this);
616 }
617 } else if(SIZE - divs == 1) {
618 size_t index = 0;
619 for(; index < SIZE; index++) {
620 if(!CHILD(index).isPower() || !CHILD(index)[1].hasNegativeSign()) {
621 break;
622 }
623 }
624 if(mstruct.size() - divs == 0) {
625 if(IS_REAL(CHILD(index))) {
626 CHILD(index).number()++;
627 } else {
628 CHILD(index).calculateAdd(m_one, eo, this, index);
629 }
630 calculateMultiplyIndex(index, eo, true, mparent, index_this);
631 } else if(mstruct.size() - divs == 1) {
632 for(size_t i = 0; i < mstruct.size(); i++) {
633 if(!mstruct[i].isPower() || !mstruct[i][1].hasNegativeSign()) {
634 mstruct[i].ref();
635 CHILD(index).add_nocopy(&mstruct[i], true);
636 CHILD(index).calculateAddLast(eo, true, this, index);
637 break;
638 }
639 }
640 calculateMultiplyIndex(index, eo, true, mparent, index_this);
641 } else {
642 for(size_t i = 0; i < mstruct.size();) {
643 if(mstruct[i].isPower() && mstruct[i][1].hasNegativeSign()) {
644 mstruct.delChild(i + 1);
645 } else {
646 i++;
647 }
648 }
649 mstruct.ref();
650 CHILD(index).add_nocopy(&mstruct, true);
651 CHILD(index).calculateAddLast(eo, true, this, index);
652 calculateMultiplyIndex(index, eo, true, mparent, index_this);
653 }
654 } else {
655 for(size_t i = 0; i < SIZE;) {
656 if(CHILD(i).isPower() && CHILD(i)[1].hasNegativeSign()) {
657 ERASE(i);
658 } else {
659 i++;
660 }
661 }
662 if(mstruct.size() - divs == 0) {
663 calculateAdd(m_one, eo);
664 } else if(mstruct.size() - divs == 1) {
665 for(size_t i = 0; i < mstruct.size(); i++) {
666 if(!mstruct[i].isPower() || !mstruct[i][1].hasNegativeSign()) {
667 mstruct[i].ref();
668 add_nocopy(&mstruct[i], true);
669 calculateAddLast(eo);
670 break;
671 }
672 }
673 } else {
674 MathStructure *mstruct2 = new MathStructure();
675 mstruct2->setType(STRUCT_MULTIPLICATION);
676 for(size_t i = 0; i < mstruct.size(); i++) {
677 if(!mstruct[i].isPower() || !mstruct[i][1].hasNegativeSign()) {
678 mstruct[i].ref();
679 mstruct2->addChild_nocopy(&mstruct[i]);
680 }
681 }
682 add_nocopy(mstruct2, true);
683 calculateAddLast(eo, true, mparent, index_this);
684 }
685 for(size_t i = 0; i < mstruct.size(); i++) {
686 if(mstruct[i].isPower() && mstruct[i][1].hasNegativeSign()) {
687 mstruct[i].ref();
688 multiply_nocopy(&mstruct[i], true);
689 calculateMultiplyLast(eo);
690 }
691 }
692 }
693 return 1;
694 }
695
696 break;
697 }
698 case STRUCT_POWER: {
699 if(eo.combine_divisions && mstruct[1].hasNegativeSign()) {
700 // y/x+1/x=(y+1)/x (eo.combine_divisions is not used anymore)
701 bool b = false;
702 size_t index = 0;
703 for(size_t i = 0; i < SIZE; i++) {
704 if(CHILD(i).isPower() && CHILD(i)[1].hasNegativeSign()) {
705 if(b) {
706 b = false;
707 break;
708 }
709 if(mstruct == CHILD(i)) {
710 index = i;
711 b = true;
712 }
713 if(!b) break;
714 }
715 }
716 if(b) {
717 if(SIZE == 2) {
718 if(index == 0) setToChild(2, true);
719 else setToChild(1, true);
720 } else {
721 ERASE(index);
722 }
723 calculateAdd(m_one, eo);
724 mstruct.ref();
725 multiply_nocopy(&mstruct, false);
726 calculateMultiplyLast(eo, true, mparent, index_this);
727 return 1;
728 }
729 }
730 if(eo.transform_trigonometric_functions && SIZE == 2 && CHILD(0).isNumber() && mstruct[0].isFunction()) {
731 if((mstruct[0].function()->id() == FUNCTION_ID_COS || mstruct[0].function()->id() == FUNCTION_ID_SIN) && !FUNCTION_PROTECTED(eo, mstruct[0].function()->id() == FUNCTION_ID_SIN ? FUNCTION_ID_COS : FUNCTION_ID_SIN) && mstruct[0].size() == 1 && mstruct[1].isNumber() && mstruct[1].number().isTwo()) {
732 if(CHILD(1).isPower() && CHILD(1)[0].isFunction() && CHILD(1)[0].function()->id() == (mstruct[0].function()->id() == FUNCTION_ID_SIN ? FUNCTION_ID_COS : FUNCTION_ID_SIN) && CHILD(1)[0].size() == 1 && CHILD(1)[1].isNumber() && CHILD(1)[1].number().isTwo() && mstruct[0][0] == CHILD(1)[0][0]) {
733 // a*sin(x)^2+cos(x)^2=1+(a-1)*sin(x), a*cos(x)^2+sin(x)^2=1+(a-1)*cos(x)
734 if(CHILD(0).calculateSubtract(m_one, eo)) {
735 add(m_one);
736 MERGE_APPROX_AND_PREC(mstruct)
737 return 1;
738 }
739 }
740 } else if((mstruct[0].function()->id() == FUNCTION_ID_COSH || mstruct[0].function()->id() == FUNCTION_ID_SINH) && !FUNCTION_PROTECTED(eo, mstruct[0].function()->id() == FUNCTION_ID_SINH ? FUNCTION_ID_COSH : FUNCTION_ID_SINH) && mstruct[0].size() == 1 && mstruct[1].isNumber() && mstruct[1].number().isTwo()) {
741 if(CHILD(1).isPower() && CHILD(1)[0].isFunction() && CHILD(1)[0].function()->id() == (mstruct[0].function()->id() == FUNCTION_ID_SINH ? FUNCTION_ID_COSH : FUNCTION_ID_SINH) && CHILD(1)[0].size() == 1 && CHILD(1)[1].isNumber() && CHILD(1)[1].number().isTwo() && mstruct[0][0] == CHILD(1)[0][0]) {
742 // a*sinh(x)^2+cosh(x)^2=1+(a+1)*sinh(x), a*cosh(x)^2+sinh(x)^2=(a+1)*cosh(x)-1
743 if(CHILD(0).calculateAdd(m_one, eo)) {
744 add(CHILD(1)[0].function()->id() == FUNCTION_ID_SINH ? m_one : m_minus_one);
745 MERGE_APPROX_AND_PREC(mstruct)
746 return 1;
747 }
748 }
749 }
750 }
751 }
752 default: {
753 if(SIZE == 2 && CHILD(0).isNumber() && CHILD(1) == mstruct) {
754 // ax+x=(a+1)x
755 CHILD(0).number()++;
756 MERGE_APPROX_AND_PREC(mstruct)
757 calculateMultiplyIndex(0, eo, true, mparent, index_this);
758 return 1;
759 }
760 if(eo.transform_trigonometric_functions && SIZE == 2 && CHILD(1).isPower() && CHILD(1)[0].isFunction() && CHILD(1)[0].function() != eo.protected_function && CHILD(1)[1] == nr_two && CHILD(1)[0].size() == 1) {
761 if(mstruct.isNumber() && CHILD(0).isNumber()) {
762 if(CHILD(1)[0].function()->id() == FUNCTION_ID_SIN && mstruct.number() == -CHILD(0).number()) {
763 // a*sin(x)^2-a=a*cos(x)^2
764 CHILD(1)[0].setFunctionId(FUNCTION_ID_COS);
765 MERGE_APPROX_AND_PREC(mstruct)
766 calculateNegate(eo, mparent, index_this);
767 return 1;
768 } else if(CHILD(1)[0].function()->id() == FUNCTION_ID_COS && mstruct.number() == -CHILD(0).number()) {
769 // a*cos(x)^2-a=a*sin(x)^2
770 CHILD(1)[0].setFunctionId(FUNCTION_ID_SIN);
771 MERGE_APPROX_AND_PREC(mstruct)
772 calculateNegate(eo, mparent, index_this);
773 return 1;
774 } else if(CHILD(1)[0].function()->id() == FUNCTION_ID_COSH && mstruct.number() == -CHILD(0).number()) {
775 // a*cosh(x)^2-a=a*sinh(x)^2
776 MERGE_APPROX_AND_PREC(mstruct)
777 CHILD(1)[0].setFunctionId(FUNCTION_ID_SINH);
778 return 1;
779 } else if(CHILD(1)[0].function()->id() == FUNCTION_ID_SINH && mstruct == CHILD(0)) {
780 // a*sinh(x)^2+a=a*cosh(x)^2
781 CHILD(1)[0].setFunctionId(FUNCTION_ID_COSH);
782 MERGE_APPROX_AND_PREC(mstruct)
783 return 1;
784 }
785 }
786 } else if(eo.transform_trigonometric_functions && SIZE == 3 && CHILD(0).isMinusOne()) {
787 size_t i = 0;
788 if(CHILD(1).isPower() && CHILD(1)[0].isFunction() && (CHILD(1)[0].function()->id() == FUNCTION_ID_SIN || CHILD(1)[0].function()->id() == FUNCTION_ID_COS || CHILD(1)[0].function()->id() == FUNCTION_ID_COSH) && CHILD(1)[0].function() != eo.protected_function && CHILD(1)[1] == nr_two && CHILD(1)[0].size() == 1 && CHILD(2) == mstruct) i = 1;
789 if(CHILD(2).isPower() && CHILD(2)[0].isFunction() && (CHILD(2)[0].function()->id() == FUNCTION_ID_SIN || CHILD(2)[0].function()->id() == FUNCTION_ID_COS || CHILD(2)[0].function()->id() == FUNCTION_ID_COSH) && CHILD(2)[0].function() != eo.protected_function && CHILD(2)[1] == nr_two && CHILD(2)[0].size() == 1 && CHILD(1) == mstruct) i = 2;
790 if(i > 0) {
791 if(CHILD(i)[0].function()->id() == FUNCTION_ID_SIN) {
792 // -y*sin(x)^2+y=y*cos(x)^2
793 CHILD(i)[0].setFunctionId(FUNCTION_ID_COS);
794 MERGE_APPROX_AND_PREC(mstruct)
795 calculateNegate(eo, mparent, index_this);
796 return 1;
797 } else if(CHILD(i)[0].function()->id() == FUNCTION_ID_COS) {
798 // -y*cos(x)^2+y=y*sin(x)^2
799 CHILD(i)[0].setFunctionId(FUNCTION_ID_SIN);
800 MERGE_APPROX_AND_PREC(mstruct)
801 calculateNegate(eo, mparent, index_this);
802 return 1;
803 } else if(CHILD(i)[0].function()->id() == FUNCTION_ID_COSH) {
804 // -y*cosh(x)^2+y=y*sinh(x)^2
805 MERGE_APPROX_AND_PREC(mstruct)
806 CHILD(i)[0].setFunctionId(FUNCTION_ID_SINH);
807 return 1;
808 }
809 }
810 }
811 if(mstruct.isDateTime() || (mstruct.isFunction() && mstruct.function()->id() == FUNCTION_ID_SIGNUM && !FUNCTION_PROTECTED(eo, FUNCTION_ID_SIGNUM))) {
812 // try again with reversed order
813 return 0;
814 }
815 }
816 }
817 break;
818 }
819 case STRUCT_POWER: {
820 if(CHILD(0).isFunction() && (CHILD(0).function()->id() == FUNCTION_ID_COS || CHILD(0).function()->id() == FUNCTION_ID_SIN) && eo.protected_function != CHILD(0).function() && CHILD(0).size() == 1 && CHILD(1).isNumber() && CHILD(1).number().isTwo()) {
821 if(eo.transform_trigonometric_functions && mstruct.isMinusOne()) {
822 // sin(x)^2-1=-cos(x)^2, cos(x)^2-1=-sin(x)^2
823 CHILD(0).setFunctionId(CHILD(0).function()->id() == FUNCTION_ID_SIN ? FUNCTION_ID_COS : FUNCTION_ID_SIN);
824 negate();
825 MERGE_APPROX_AND_PREC(mstruct)
826 return 1;
827 } else if(mstruct.isPower() && mstruct[0].isFunction() && mstruct[0].function()->id() == (CHILD(0).function()->id() == FUNCTION_ID_SIN ? FUNCTION_ID_COS : FUNCTION_ID_SIN) && eo.protected_function != mstruct[0].function() && mstruct[0].size() == 1 && mstruct[1].isNumber() && mstruct[1].number().isTwo() && CHILD(0)[0] == mstruct[0][0]) {
828 // cos(x)^2+sin(x)^2=1
829 set(1, 1, 0, true);
830 MERGE_APPROX_AND_PREC(mstruct)
831 return 1;
832 }
833 } else if(eo.transform_trigonometric_functions && CHILD(0).isFunction() && (CHILD(0).function()->id() == FUNCTION_ID_COSH || CHILD(0).function()->id() == FUNCTION_ID_SINH) && eo.protected_function != CHILD(0).function() && CHILD(0).size() == 1 && CHILD(1).isNumber() && CHILD(1).number().isTwo()) {
834 if(CHILD(0).function()->id() == FUNCTION_ID_SINH && mstruct.isOne()) {
835 // sinh(x)^2+1=cosh(x)^2
836 CHILD(0).setFunctionId(FUNCTION_ID_COSH);
837 MERGE_APPROX_AND_PREC(mstruct)
838 return 1;
839 } else if(CHILD(0).function()->id() == FUNCTION_ID_COSH && mstruct.isMinusOne()) {
840 // cosh(x)^2-1=sinh(x)^2
841 CHILD(0).setFunctionId(FUNCTION_ID_SINH);
842 MERGE_APPROX_AND_PREC(mstruct)
843 return 1;
844 } else if(mstruct.isPower() && mstruct[0].isFunction() && mstruct[0].function()->id() == (CHILD(0).function()->id() == FUNCTION_ID_SINH ? FUNCTION_ID_COSH : FUNCTION_ID_SINH) && !FUNCTION_PROTECTED(eo, FUNCTION_ID_COSH) && mstruct[0].size() == 1 && mstruct[1].isNumber() && mstruct[1].number().isTwo() && CHILD(0)[0] == mstruct[0][0]) {
845 // sinh(x)^2+cosh(x)^2=2*sinh(x)^2+1
846 CHILD(0).setFunctionId(FUNCTION_ID_SINH);
847 multiply(nr_two);
848 add(m_one);
849 MERGE_APPROX_AND_PREC(mstruct)
850 return 1;
851 }
852 }
853 goto default_addition_merge;
854 }
855 case STRUCT_FUNCTION: {
856 if(o_function->id() == FUNCTION_ID_SIGNUM && mstruct.isMultiplication() && !FUNCTION_PROTECTED(eo, FUNCTION_ID_SIGNUM)) {
857 if((SIZE == 1 || SIZE == 2) && CHILD(0).isAddition() && CHILD(0).size() == 2 && (CHILD(0)[0].isOne() || CHILD(0)[1].isOne()) && CHILD(0).representsReal(true)) {
858 // sgn(x+1)+sgn(x+1)x=abs(x+1)
859 for(size_t im = 0; im < mstruct.size(); im++) {
860 if(mstruct[im] == *this) {
861 MathStructure *mchild = &mstruct[im];
862 mchild->ref();
863 mstruct.delChild(im + 1);
864 if((mstruct.size() == 1 && mstruct[0] == CHILD(0)[CHILD(0)[0].isOne() ? 1 : 0]) || (mstruct.size() > 1 && mstruct == CHILD(0)[CHILD(0)[0].isOne() ? 1 : 0])) {
865 mchild->unref();
866 setFunctionId(FUNCTION_ID_ABS);
867 if(SIZE == 2) {ERASE(1);}
868 MERGE_APPROX_AND_PREC(mstruct)
869 return 1;
870 }
871 mstruct.insertChild_nocopy(mchild, im + 1);
872 }
873 }
874 }
875 } else if(mstruct.isFunction() && ((o_function->id() == FUNCTION_ID_ASIN && mstruct.function()->id() == FUNCTION_ID_ACOS) || (o_function->id() == FUNCTION_ID_ACOS && mstruct.function()->id() == FUNCTION_ID_ASIN)) && !FUNCTION_PROTECTED(eo, FUNCTION_ID_ACOS) && !FUNCTION_PROTECTED(eo, FUNCTION_ID_ASIN) && SIZE == 1 && mstruct.size() == 1 && CHILD(0) == mstruct[0]) {
876 // asin(x)+acos(x)=pi/2
877 switch(eo.parse_options.angle_unit) {
878 case ANGLE_UNIT_DEGREES: {set(90, 1, 0, true); break;}
879 case ANGLE_UNIT_GRADIANS: {set(100, 1, 0, true); break;}
880 case ANGLE_UNIT_RADIANS: {set(CALCULATOR->getVariableById(VARIABLE_ID_PI), true); multiply(nr_half); calculatesub(eo, eo, true); break;}
881 default: {set(CALCULATOR->getVariableById(VARIABLE_ID_PI), true); multiply(nr_half); if(CALCULATOR->getRadUnit()) {multiply(CALCULATOR->getRadUnit(), true);} calculatesub(eo, eo, true); break;}
882 }
883 MERGE_APPROX_AND_PREC(mstruct)
884 return 1;
885 } else if(mstruct.isFunction() && ((o_function->id() == FUNCTION_ID_SINH && mstruct.function()->id() == FUNCTION_ID_COSH) || (o_function->id() == FUNCTION_ID_COSH && mstruct.function()->id() == FUNCTION_ID_SINH)) && !FUNCTION_PROTECTED(eo, FUNCTION_ID_COSH) && !FUNCTION_PROTECTED(eo, FUNCTION_ID_SINH) && SIZE == 1 && mstruct.size() == 1 && CHILD(0) == mstruct[0]) {
886 // sinh(x)+cosh(x)=e^x
887 MathStructure *mexp = &CHILD(0);
888 mexp->ref();
889 set(CALCULATOR->getVariableById(VARIABLE_ID_E), true);
890 calculatesub(eo, eo, true);
891 raise_nocopy(mexp);
892 MERGE_APPROX_AND_PREC(mstruct)
893 calculateRaiseExponent(eo, mparent, index_this);
894 return 1;
895 } else if(mstruct.isFunction() && o_function->id() == FUNCTION_ID_STRIP_UNITS && mstruct.function()->id() == FUNCTION_ID_STRIP_UNITS && mstruct.size() == 1 && SIZE == 1) {
896 // nounit(x)+nounit(y)=nounit(x+y)
897 mstruct[0].ref();
898 CHILD(0).add_nocopy(&mstruct[0]);
899 return 1;
900 }
901 goto default_addition_merge;
902 }
903 case STRUCT_DATETIME: {
904 if(mstruct.isDateTime()) {
905 // date/time + date/time
906 if(o_datetime->add(*mstruct.datetime())) {
907 MERGE_APPROX_AND_PREC(mstruct)
908 return 1;
909 }
910 } else if(mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0].isMinusOne() && mstruct[1].isDateTime() && (CALCULATOR->getUnitById(UNIT_ID_SECOND) || CALCULATOR->getUnitById(UNIT_ID_DAY))) {
911 if(CALCULATOR->getUnitById(UNIT_ID_DAY) && !mstruct[1].datetime()->timeIsSet() && !o_datetime->timeIsSet()) {
912 // date1 - date2 = date2.daysTo(date1)
913 Number ndays = mstruct[1].datetime()->daysTo(*o_datetime);
914 set(ndays, true);
915 multiply(CALCULATOR->getUnitById(UNIT_ID_DAY));
916 } else {
917 // time1 - time2 = time2.secondsTo(time1)
918 Number nsecs = mstruct[1].datetime()->secondsTo(*o_datetime, true);
919 set(nsecs, true);
920 multiply(CALCULATOR->getUnitById(UNIT_ID_SECOND), true);
921 }
922 MERGE_APPROX_AND_PREC(mstruct)
923 return 1;
924 } else if(CALCULATOR->getUnitById(UNIT_ID_SECOND) && ((mstruct.isUnit() && mstruct.unit()->baseUnit() == CALCULATOR->getUnitById(UNIT_ID_SECOND) && mstruct.unit()->baseExponent() == 1 && !mstruct.unit()->hasNonlinearRelationTo(CALCULATOR->getUnitById(UNIT_ID_SECOND))) || (mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0].isNumber() && mstruct[0].number().isReal() && !mstruct[0].number().isInterval() && mstruct[1].isUnit() && mstruct[1].unit()->baseUnit() == CALCULATOR->getUnitById(UNIT_ID_SECOND) && mstruct[1].unit()->baseExponent() == 1 && !mstruct[1].unit()->hasNonlinearRelationTo(CALCULATOR->getUnitById(UNIT_ID_SECOND))))) {
925 MathStructure mmul(1, 1, 0);
926 Unit *u;
927 if(mstruct.isMultiplication()) {
928 mmul = mstruct[0];
929 u = mstruct[1].unit();
930 } else {
931 u = mstruct.unit();
932 }
933 if(CALCULATOR->getUnitById(UNIT_ID_MONTH) && u != CALCULATOR->getUnitById(UNIT_ID_YEAR) && (u == CALCULATOR->getUnitById(UNIT_ID_MONTH) || u->isChildOf(CALCULATOR->getUnitById(UNIT_ID_MONTH)))) {
934 // date + a*month
935 if(u != CALCULATOR->getUnitById(UNIT_ID_MONTH)) {
936 CALCULATOR->getUnitById(UNIT_ID_MONTH)->convert(u, mmul);
937 mmul.eval(eo);
938 }
939 if(mmul.isNumber() && o_datetime->addMonths(mmul.number())) {
940 MERGE_APPROX_AND_PREC(mstruct)
941 return 1;
942 }
943 } else if(CALCULATOR->getUnitById(UNIT_ID_YEAR) && (u == CALCULATOR->getUnitById(UNIT_ID_YEAR) || u->isChildOf(CALCULATOR->getUnitById(UNIT_ID_YEAR)))) {
944 // date + a*year
945 if(u != CALCULATOR->getUnitById(UNIT_ID_YEAR)) {
946 CALCULATOR->getUnitById(UNIT_ID_YEAR)->convert(u, mmul);
947 mmul.eval(eo);
948 }
949 if(mmul.isNumber() && o_datetime->addYears(mmul.number())) {
950 MERGE_APPROX_AND_PREC(mstruct)
951 return 1;
952 }
953 } else if(CALCULATOR->getUnitById(UNIT_ID_DAY) && (u == CALCULATOR->getUnitById(UNIT_ID_DAY) || u->isChildOf(CALCULATOR->getUnitById(UNIT_ID_DAY)))) {
954 // date + a*day
955 if(u != CALCULATOR->getUnitById(UNIT_ID_DAY)) {
956 CALCULATOR->getUnitById(UNIT_ID_DAY)->convert(u, mmul);
957 mmul.eval(eo);
958 }
959 if(mmul.isNumber() && o_datetime->addDays(mmul.number())) {
960 MERGE_APPROX_AND_PREC(mstruct)
961 return 1;
962 }
963 } else if(CALCULATOR->getUnitById(UNIT_ID_HOUR) && (u == CALCULATOR->getUnitById(UNIT_ID_HOUR) || u->isChildOf(CALCULATOR->getUnitById(UNIT_ID_HOUR)))) {
964 // date + a*hour
965 if(u != CALCULATOR->getUnitById(UNIT_ID_HOUR)) {
966 CALCULATOR->getUnitById(UNIT_ID_HOUR)->convert(u, mmul);
967 mmul.eval(eo);
968 }
969 if(mmul.isNumber() && o_datetime->addHours(mmul.number())) {
970 MERGE_APPROX_AND_PREC(mstruct)
971 return 1;
972 }
973 } else if(CALCULATOR->getUnitById(UNIT_ID_MINUTE) && (u == CALCULATOR->getUnitById(UNIT_ID_MINUTE) || u->isChildOf(CALCULATOR->getUnitById(UNIT_ID_MINUTE)))) {
974 // date + a*minute
975 if(u != CALCULATOR->getUnitById(UNIT_ID_MINUTE)) {
976 CALCULATOR->getUnitById(UNIT_ID_MINUTE)->convert(u, mmul);
977 mmul.eval(eo);
978 }
979 if(mmul.isNumber() && o_datetime->addMinutes(mmul.number())) {
980 MERGE_APPROX_AND_PREC(mstruct)
981 return 1;
982 }
983 } else {
984 // date + a*second
985 MathStructure mmulb(mmul);
986 if(u != CALCULATOR->getUnitById(UNIT_ID_SECOND)) {
987 u->convertToBaseUnit(mmul);
988 mmul.eval(eo);
989 }
990 if(mmul.isNumber() && o_datetime->addSeconds(mmul.number(), true)) {
991 MERGE_APPROX_AND_PREC(mstruct)
992 return 1;
993 }
994 }
995 }
996 }
997 default: {
998 default_addition_merge:
999 switch(mstruct.type()) {
1000 case STRUCT_VECTOR: {}
1001 case STRUCT_DATETIME: {}
1002 case STRUCT_ADDITION: {}
1003 case STRUCT_MULTIPLICATION: {
1004 // try again with reversed order
1005 return 0;
1006 }
1007 default: {
1008 if(equals(mstruct)) {
1009 // x+x=2x
1010 multiply_nocopy(new MathStructure(2, 1, 0), true);
1011 MERGE_APPROX_AND_PREC(mstruct)
1012 calculateMultiplyLast(eo, true, mparent, index_this);
1013 return 1;
1014 }
1015 }
1016 }
1017 }
1018 }
1019 return -1;
1020 }
1021
reducable(const MathStructure & mnum,const MathStructure & mden,Number & nr)1022 bool reducable(const MathStructure &mnum, const MathStructure &mden, Number &nr) {
1023 switch(mnum.type()) {
1024 case STRUCT_NUMBER: {}
1025 case STRUCT_ADDITION: {
1026 break;
1027 }
1028 default: {
1029 bool reduce = true;
1030 for(size_t i = 0; i < mden.size() && reduce; i++) {
1031 switch(mden[i].type()) {
1032 case STRUCT_MULTIPLICATION: {
1033 reduce = false;
1034 for(size_t i2 = 0; i2 < mden[i].size(); i2++) {
1035 if(mnum == mden[i][i2]) {
1036 reduce = true;
1037 if(!nr.isOne() && !nr.isFraction()) nr.set(1, 1, 0);
1038 break;
1039 } else if(mden[i][i2].isPower() && mden[i][i2][1].isNumber() && mden[i][i2][1].number().isReal() && mnum == mden[i][i2][0]) {
1040 if(!mden[i][i2][1].number().isPositive()) {
1041 break;
1042 }
1043 if(mden[i][i2][1].number().isLessThan(nr)) nr = mden[i][i2][1].number();
1044 reduce = true;
1045 break;
1046 }
1047 }
1048 break;
1049 }
1050 case STRUCT_POWER: {
1051 if(mden[i][1].isNumber() && mden[i][1].number().isReal() && mnum == mden[i][0]) {
1052 if(!mden[i][1].number().isPositive()) {
1053 reduce = false;
1054 break;
1055 }
1056 if(mden[i][1].number().isLessThan(nr)) nr = mden[i][1].number();
1057 break;
1058 }
1059 }
1060 default: {
1061 if(mnum != mden[i]) {
1062 reduce = false;
1063 break;
1064 }
1065 if(!nr.isOne() && !nr.isFraction()) nr.set(1, 1, 0);
1066 }
1067 }
1068 }
1069 return reduce;
1070 }
1071 }
1072 return false;
1073 }
reduce(const MathStructure & mnum,MathStructure & mden,Number & nr,const EvaluationOptions & eo)1074 void reduce(const MathStructure &mnum, MathStructure &mden, Number &nr, const EvaluationOptions &eo) {
1075 switch(mnum.type()) {
1076 case STRUCT_NUMBER: {}
1077 case STRUCT_ADDITION: {
1078 break;
1079 }
1080 default: {
1081 for(size_t i = 0; i < mden.size(); i++) {
1082 switch(mden[i].type()) {
1083 case STRUCT_MULTIPLICATION: {
1084 for(size_t i2 = 0; i2 < mden[i].size(); i2++) {
1085 if(mden[i][i2] == mnum) {
1086 if(!nr.isOne()) {
1087 MathStructure *mexp = new MathStructure(1, 1, 0);
1088 mexp->number() -= nr;
1089 mden[i][i2].raise_nocopy(mexp);
1090 mden[i][i2].calculateRaiseExponent(eo);
1091 if(mden[i][i2].isOne() && mden[i].size() > 1) {
1092 mden[i].delChild(i2 + 1);
1093 if(mden[i].size() == 1) {
1094 mden[i].setToChild(1, true, &mden, i + 1);
1095 }
1096 }
1097 } else {
1098 if(mden[i].size() == 1) {
1099 mden[i].set(m_one);
1100 } else {
1101 mden[i].delChild(i2 + 1);
1102 if(mden[i].size() == 1) {
1103 mden[i].setToChild(1, true, &mden, i + 1);
1104 }
1105 }
1106 }
1107 break;
1108 } else if(mden[i][i2].isPower() && mden[i][i2][1].isNumber() && mden[i][i2][1].number().isReal() && mnum.equals(mden[i][i2][0])) {
1109 mden[i][i2][1].number() -= nr;
1110 if(mden[i][i2][1].number().isOne()) {
1111 mden[i][i2].setToChild(1, true, &mden[i], i2 + 1);
1112 } else {
1113 mden[i][i2].calculateRaiseExponent(eo);
1114 if(mden[i][i2].isOne() && mden[i].size() > 1) {
1115 mden[i].delChild(i2 + 1);
1116 if(mden[i].size() == 1) {
1117 mden[i].setToChild(1, true, &mden, i + 1);
1118 }
1119 }
1120 }
1121 break;
1122 }
1123 }
1124 break;
1125 }
1126 case STRUCT_POWER: {
1127 if(mden[i][1].isNumber() && mden[i][1].number().isReal() && mnum.equals(mden[i][0])) {
1128 mden[i][1].number() -= nr;
1129 if(mden[i][1].number().isOne()) {
1130 mden[i].setToChild(1, true, &mden, i + 1);
1131 } else {
1132 mden[i].calculateRaiseExponent(eo, &mden, i);
1133 }
1134 break;
1135 }
1136 }
1137 default: {
1138 if(!nr.isOne()) {
1139 MathStructure *mexp = new MathStructure(1, 1, 0);
1140 mexp->number() -= nr;
1141 mden[i].raise_nocopy(mexp);
1142 mden[i].calculateRaiseExponent(eo, &mden, 1);
1143 } else {
1144 mden[i].set(m_one);
1145 }
1146 }
1147 }
1148 }
1149 mden.calculatesub(eo, eo, false);
1150 }
1151 }
1152 }
1153
addablePower(const MathStructure & mstruct,const EvaluationOptions & eo)1154 bool addablePower(const MathStructure &mstruct, const EvaluationOptions &eo) {
1155 if(mstruct[0].representsNonNegative(true)) return true;
1156 if(mstruct[1].representsInteger()) return true;
1157 //return eo.allow_complex && mstruct[0].representsNegative(true) && mstruct[1].isNumber() && mstruct[1].number().isRational() && mstruct[1].number().denominatorIsEven();
1158 return eo.allow_complex && mstruct[1].isNumber() && mstruct[1].number().isRational() && mstruct[1].number().denominatorIsEven();
1159 }
1160
cmp_num_abs_2_to_den(const Number & nr)1161 int cmp_num_abs_2_to_den(const Number &nr) {
1162 mpz_t z_num;
1163 mpz_init(z_num);
1164 mpz_mul_ui(z_num, mpq_numref(nr.internalRational()), 2);
1165 int i = mpz_cmpabs(z_num, mpq_denref(nr.internalRational()));
1166 mpz_clear(z_num);
1167 return i;
1168 }
1169
merge_multiplication(MathStructure & mstruct,const EvaluationOptions & eo,MathStructure * mparent,size_t index_this,size_t index_mstruct,bool reversed,bool do_append)1170 int MathStructure::merge_multiplication(MathStructure &mstruct, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this, size_t index_mstruct, bool reversed, bool do_append) {
1171 // test if two factors can be merged
1172 if(mstruct.type() == STRUCT_NUMBER && m_type == STRUCT_NUMBER) {
1173 // both factors are numbers try Number::multiply() (might never fail for infinite values)
1174 Number nr(o_number);
1175 if(nr.multiply(mstruct.number()) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || mstruct.number().isApproximate()) && (eo.allow_complex || !nr.isComplex() || o_number.isComplex() || mstruct.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || o_number.includesInfinity() || mstruct.number().includesInfinity())) {
1176 if(o_number == nr) {
1177 o_number = nr;
1178 numberUpdated();
1179 return 2;
1180 }
1181 o_number = nr;
1182 numberUpdated();
1183 return 1;
1184 }
1185 return -1;
1186 }
1187 if(mstruct.isOne()) {
1188 // x*1=x
1189 MERGE_APPROX_AND_PREC(mstruct)
1190 return 2;
1191 } else if(isOne()) {
1192 // 1*x=x
1193 if(mparent) {
1194 mparent->swapChildren(index_this + 1, index_mstruct + 1);
1195 } else {
1196 set_nocopy(mstruct, true);
1197 }
1198 return 3;
1199 }
1200 if(m_type == STRUCT_NUMBER && o_number.isInfinite()) {
1201 if(o_number.isMinusInfinity(false)) {
1202 if(mstruct.representsPositive(false)) {
1203 // (-infinity)*x=-infinity if x is positive
1204 MERGE_APPROX_AND_PREC(mstruct)
1205 return 2;
1206 } else if(mstruct.representsNegative(false)) {
1207 // (-infinity)*x=infinity if x is negative
1208 o_number.setPlusInfinity();
1209 MERGE_APPROX_AND_PREC(mstruct)
1210 return 1;
1211 }
1212 } else if(o_number.isPlusInfinity(false)) {
1213 if(mstruct.representsPositive(false)) {
1214 // infinity*x=infinity if x is negative
1215 MERGE_APPROX_AND_PREC(mstruct)
1216 return 2;
1217 } else if(mstruct.representsNegative(false)) {
1218 // infinity*x=-infinity if x is negative
1219 o_number.setMinusInfinity();
1220 MERGE_APPROX_AND_PREC(mstruct)
1221 return 1;
1222 }
1223 }
1224 if(eo.approximation == APPROXIMATION_EXACT) {
1225 // test approximate value
1226 MathStructure mtest(mstruct);
1227 CALCULATOR->beginTemporaryEnableIntervalArithmetic();
1228 if(CALCULATOR->usesIntervalArithmetic()) {
1229 CALCULATOR->beginTemporaryStopMessages();
1230 EvaluationOptions eo2 = eo;
1231 eo2.approximation = APPROXIMATION_APPROXIMATE;
1232 if(eo2.interval_calculation == INTERVAL_CALCULATION_NONE) eo2.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC;
1233 mtest.calculateFunctions(eo2);
1234 mtest.calculatesub(eo2, eo2);
1235 CALCULATOR->endTemporaryStopMessages();
1236 }
1237 CALCULATOR->endTemporaryEnableIntervalArithmetic();
1238 if(o_number.isMinusInfinity(false)) {
1239 if(mtest.representsPositive(false)) {
1240 MERGE_APPROX_AND_PREC(mstruct)
1241 return 2;
1242 } else if(mtest.representsNegative(false)) {
1243 o_number.setPlusInfinity();
1244 MERGE_APPROX_AND_PREC(mstruct)
1245 return 1;
1246 }
1247 } else if(o_number.isPlusInfinity(false)) {
1248 if(mtest.representsPositive(false)) {
1249 MERGE_APPROX_AND_PREC(mstruct)
1250 return 2;
1251 } else if(mtest.representsNegative(false)) {
1252 o_number.setMinusInfinity();
1253 MERGE_APPROX_AND_PREC(mstruct)
1254 return 1;
1255 }
1256 }
1257 }
1258 } else if(mstruct.isNumber() && mstruct.number().isInfinite()) {
1259 if(mstruct.number().isMinusInfinity(false)) {
1260 if(representsPositive(false)) {
1261 // x*(-infinity)=-infinity if x is positive
1262 clear(true);
1263 o_number.setMinusInfinity();
1264 MERGE_APPROX_AND_PREC(mstruct)
1265 return 1;
1266 } else if(representsNegative(false)) {
1267 // x*(-infinity)=infinity if x is negative
1268 clear(true);
1269 o_number.setPlusInfinity();
1270 MERGE_APPROX_AND_PREC(mstruct)
1271 return 1;
1272 }
1273 } else if(mstruct.number().isPlusInfinity(false)) {
1274 if(representsPositive(false)) {
1275 // x*infinity=infinity if x is positive
1276 clear(true);
1277 o_number.setPlusInfinity();
1278 MERGE_APPROX_AND_PREC(mstruct)
1279 return 1;
1280 } else if(representsNegative(false)) {
1281 // x*infinity=-infinity if x is negative
1282 clear(true);
1283 o_number.setMinusInfinity();
1284 MERGE_APPROX_AND_PREC(mstruct)
1285 return 1;
1286 }
1287 }
1288 if(eo.approximation == APPROXIMATION_EXACT) {
1289 // test approximate value
1290 MathStructure mtest(*this);
1291 CALCULATOR->beginTemporaryEnableIntervalArithmetic();
1292 if(CALCULATOR->usesIntervalArithmetic()) {
1293 CALCULATOR->beginTemporaryStopMessages();
1294 EvaluationOptions eo2 = eo;
1295 eo2.approximation = APPROXIMATION_APPROXIMATE;
1296 if(eo2.interval_calculation == INTERVAL_CALCULATION_NONE) eo2.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC;
1297 mtest.calculateFunctions(eo2);
1298 mtest.calculatesub(eo2, eo2);
1299 CALCULATOR->endTemporaryStopMessages();
1300 }
1301 CALCULATOR->endTemporaryEnableIntervalArithmetic();
1302 if(mstruct.number().isMinusInfinity(false)) {
1303 if(mtest.representsPositive(false)) {
1304 clear(true);
1305 o_number.setMinusInfinity();
1306 MERGE_APPROX_AND_PREC(mstruct)
1307 return 1;
1308 } else if(mtest.representsNegative(false)) {
1309 clear(true);
1310 o_number.setPlusInfinity();
1311 MERGE_APPROX_AND_PREC(mstruct)
1312 return 1;
1313 }
1314 } else if(mstruct.number().isPlusInfinity(false)) {
1315 if(mtest.representsPositive(false)) {
1316 clear(true);
1317 o_number.setPlusInfinity();
1318 MERGE_APPROX_AND_PREC(mstruct)
1319 return 1;
1320 } else if(mtest.representsNegative(false)) {
1321 clear(true);
1322 o_number.setMinusInfinity();
1323 MERGE_APPROX_AND_PREC(mstruct)
1324 return 1;
1325 }
1326 }
1327 }
1328 }
1329
1330 if(representsUndefined() || mstruct.representsUndefined()) return -1;
1331
1332 // check if factors are numerator and denominator, and denominator is polynomial
1333 const MathStructure *mnum = NULL, *mden = NULL;
1334 bool b_nonzero = false;
1335 if(eo.reduce_divisions) {
1336 if(!isNumber() && mstruct.isPower() && mstruct[0].isAddition() && mstruct[0].size() > 1 && mstruct[1].isNumber() && mstruct[1].number().isMinusOne()) {
1337 // second factor is denominator (exponent = -1)
1338 if((!isPower() || !CHILD(1).hasNegativeSign()) && representsNumber() && mstruct[0].representsNumber()) {
1339 if((!eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !mstruct[0].representsZero(true)) || mstruct[0].representsNonZero(true)) {
1340 // denominator is not zero
1341 b_nonzero = true;
1342 }
1343 if(b_nonzero || (eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !mstruct[0].representsZero(true))) {
1344 mnum = this;
1345 mden = &mstruct[0];
1346 }
1347 }
1348 } else if(!mstruct.isNumber() && isPower() && CHILD(0).isAddition() && CHILD(0).size() > 1 && CHILD(1).isNumber() && CHILD(1).number().isMinusOne()) {
1349 // first factor is denominator (exponent = -1)
1350 if((!mstruct.isPower() || !mstruct[1].hasNegativeSign()) && mstruct.representsNumber() && CHILD(0).representsNumber()) {
1351 if((!eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !CHILD(0).representsZero(true)) || CHILD(0).representsNonZero(true)) {
1352 // denominator is not zero
1353 b_nonzero = true;
1354 }
1355 if(b_nonzero || (eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !CHILD(0).representsZero(true))) {
1356 mnum = &mstruct;
1357 mden = &CHILD(0);
1358 }
1359 }
1360 }
1361 }
1362
1363 // look for common factors in numerator and denominator
1364 if(mnum && mden && eo.reduce_divisions) {
1365 switch(mnum->type()) {
1366 case STRUCT_ADDITION: {
1367 // polynomial division is not handled here
1368 break;
1369 }
1370 case STRUCT_MULTIPLICATION: {
1371 Number nr;
1372 vector<Number> nrs;
1373 vector<size_t> reducables;
1374 for(size_t i = 0; i < mnum->size(); i++) {
1375 switch((*mnum)[i].type()) {
1376 case STRUCT_ADDITION: {break;}
1377 case STRUCT_POWER: {
1378 if((*mnum)[i][1].isNumber() && (*mnum)[i][1].number().isReal()) {
1379 if((*mnum)[i][1].number().isPositive()) {
1380 nr.set((*mnum)[i][1].number());
1381 if(reducable((*mnum)[i][0], *mden, nr)) {
1382 nrs.push_back(nr);
1383 reducables.push_back(i);
1384 }
1385 }
1386 break;
1387 }
1388 }
1389 default: {
1390 nr.set(1, 1, 0);
1391 if(reducable((*mnum)[i], *mden, nr)) {
1392 nrs.push_back(nr);
1393 reducables.push_back(i);
1394 }
1395 }
1396 }
1397 }
1398 if(reducables.size() > 0) {
1399 if(!b_nonzero && eo.warn_about_denominators_assumed_nonzero && !warn_about_denominators_assumed_nonzero(*mden, eo)) break;
1400 if(mnum == this) {
1401 mstruct.ref();
1402 transform_nocopy(STRUCT_MULTIPLICATION, &mstruct);
1403 } else {
1404 transform(STRUCT_MULTIPLICATION);
1405 PREPEND_REF(&mstruct);
1406 }
1407 size_t i_erased = 0;
1408 for(size_t i = 0; i < reducables.size(); i++) {
1409 switch(CHILD(0)[reducables[i] - i_erased].type()) {
1410 case STRUCT_POWER: {
1411 if(CHILD(0)[reducables[i] - i_erased][1].isNumber() && CHILD(0)[reducables[i] - i_erased][1].number().isReal()) {
1412 reduce(CHILD(0)[reducables[i] - i_erased][0], CHILD(1)[0], nrs[i], eo);
1413 if(nrs[i] == CHILD(0)[reducables[i] - i_erased][1].number()) {
1414 CHILD(0).delChild(reducables[i] - i_erased + 1);
1415 i_erased++;
1416 } else {
1417 CHILD(0)[reducables[i] - i_erased][1].number() -= nrs[i];
1418 if(CHILD(0)[reducables[i] - i_erased][1].number().isOne()) {
1419 CHILD(0)[reducables[i] - i_erased].setToChild(1, true, &CHILD(0), reducables[i] - i_erased + 1);
1420 } else {
1421 CHILD(0)[reducables[i] - i_erased].calculateRaiseExponent(eo);
1422 }
1423 CHILD(0).calculateMultiplyIndex(reducables[i] - i_erased, eo, true);
1424 }
1425 break;
1426 }
1427 }
1428 default: {
1429 reduce(CHILD(0)[reducables[i] - i_erased], CHILD(1)[0], nrs[i], eo);
1430 if(nrs[i].isOne()) {
1431 CHILD(0).delChild(reducables[i] - i_erased + 1);
1432 i_erased++;
1433 } else {
1434 MathStructure mexp(1, 1);
1435 mexp.number() -= nrs[i];
1436 CHILD(0)[reducables[i] - i_erased].calculateRaise(mexp, eo);
1437 CHILD(0).calculateMultiplyIndex(reducables[i] - i_erased, eo, true);
1438 }
1439 }
1440 }
1441 }
1442 if(CHILD(0).size() == 0) {
1443 setToChild(2, true, mparent, index_this + 1);
1444 } else if(CHILD(0).size() == 1) {
1445 CHILD(0).setToChild(1, true, this, 1);
1446 calculateMultiplyIndex(0, eo, true, mparent, index_this);
1447 } else {
1448 calculateMultiplyIndex(0, eo, true, mparent, index_this);
1449 }
1450 return 1;
1451 }
1452 break;
1453 }
1454 case STRUCT_POWER: {
1455 if((*mnum)[1].isNumber() && (*mnum)[1].number().isReal()) {
1456 if((*mnum)[1].number().isPositive()) {
1457 Number nr((*mnum)[1].number());
1458 if(reducable((*mnum)[0], *mden, nr)) {
1459 if(!b_nonzero && eo.warn_about_denominators_assumed_nonzero && !warn_about_denominators_assumed_nonzero(*mden, eo)) break;
1460 if(nr != (*mnum)[1].number()) {
1461 MathStructure mnum2((*mnum)[0]);
1462 if(mnum == this) {
1463 CHILD(1).number() -= nr;
1464 if(CHILD(1).number().isOne()) {
1465 set(mnum2);
1466 } else {
1467 calculateRaiseExponent(eo);
1468 }
1469 mstruct.ref();
1470 transform_nocopy(STRUCT_MULTIPLICATION, &mstruct);
1471 reduce(mnum2, CHILD(1)[0], nr, eo);
1472 calculateMultiplyLast(eo);
1473 } else {
1474 transform(STRUCT_MULTIPLICATION);
1475 PREPEND(mstruct);
1476 CHILD(0)[1].number() -= nr;
1477 if(CHILD(0)[1].number().isOne()) {
1478 CHILD(0) = mnum2;
1479 } else {
1480 CHILD(0).calculateRaiseExponent(eo);
1481 }
1482 reduce(mnum2, CHILD(1)[0], nr, eo);
1483 calculateMultiplyIndex(0, eo);
1484 }
1485 } else {
1486 if(mnum == this) {
1487 MathStructure mnum2((*mnum)[0]);
1488 if(mparent) {
1489 mparent->swapChildren(index_this + 1, index_mstruct + 1);
1490 reduce(mnum2, (*mparent)[index_this][0], nr, eo);
1491 } else {
1492 set_nocopy(mstruct, true);
1493 reduce(mnum2, CHILD(0), nr, eo);
1494 }
1495 } else {
1496 reduce((*mnum)[0], CHILD(0), nr, eo);
1497 }
1498 }
1499 return 1;
1500 }
1501 }
1502 break;
1503 }
1504 }
1505 default: {
1506 Number nr(1, 1);
1507 if(reducable(*mnum, *mden, nr)) {
1508 if(!b_nonzero && eo.warn_about_denominators_assumed_nonzero && !warn_about_denominators_assumed_nonzero(*mden, eo)) break;
1509 if(mnum == this) {
1510 MathStructure mnum2(*mnum);
1511 if(!nr.isOne()) {
1512 reduce(*mnum, mstruct[0], nr, eo);
1513 mstruct.calculateRaiseExponent(eo);
1514 nr.negate();
1515 nr++;
1516 calculateRaise(nr, eo);
1517 mstruct.ref();
1518 multiply_nocopy(&mstruct);
1519 calculateMultiplyLast(eo, true, mparent, index_this);
1520 } else if(mparent) {
1521 mparent->swapChildren(index_this + 1, index_mstruct + 1);
1522 reduce(mnum2, (*mparent)[index_this][0], nr, eo);
1523 (*mparent)[index_this].calculateRaiseExponent(eo, mparent, index_this);
1524 } else {
1525 set_nocopy(mstruct, true);
1526 reduce(mnum2, CHILD(0), nr, eo);
1527 calculateRaiseExponent(eo, mparent, index_this);
1528 }
1529 } else {
1530 reduce(*mnum, CHILD(0), nr, eo);
1531 if(!nr.isOne()) {
1532 calculateRaiseExponent(eo);
1533 nr.negate();
1534 nr++;
1535 mstruct.calculateRaise(nr, eo);
1536 mstruct.ref();
1537 multiply_nocopy(&mstruct);
1538 calculateMultiplyLast(eo, true, mparent, index_this);
1539 } else {
1540 calculateRaiseExponent(eo, mparent, index_this);
1541 }
1542 }
1543 return 1;
1544 }
1545 }
1546 }
1547 }
1548
1549 if(mstruct.isFunction() && eo.protected_function != mstruct.function()) {
1550 if(((mstruct.function()->id() == FUNCTION_ID_ABS && mstruct.size() == 1 && mstruct[0].isFunction() && mstruct[0].function()->id() == FUNCTION_ID_SIGNUM && mstruct[0].size() == 2) || (mstruct.function()->id() == FUNCTION_ID_SIGNUM && mstruct.size() == 2 && mstruct[0].isFunction() && mstruct[0].function()->id() == FUNCTION_ID_ABS && mstruct[0].size() == 1)) && (equals(mstruct[0][0]) || (isFunction() && o_function->id() == FUNCTION_ID_ABS && SIZE == 1 && CHILD(0) == mstruct[0][0]) || (isPower() && CHILD(0) == mstruct[0][0]) || (isPower() && CHILD(0).isFunction() && CHILD(0).function()->id() == FUNCTION_ID_ABS && CHILD(0).size() == 1 && CHILD(0)[0] == mstruct[0][0]))) {
1551 // sgn(abs(x))*x^y=x^y
1552 MERGE_APPROX_AND_PREC(mstruct)
1553 return 2;
1554 } else if(mstruct.function()->id() == FUNCTION_ID_SIGNUM && mstruct.size() == 2) {
1555 if(equals(mstruct[0]) && representsReal(true)) {
1556 // sgn(x)*x=abs(x)
1557 transformById(FUNCTION_ID_ABS);
1558 MERGE_APPROX_AND_PREC(mstruct)
1559 return 1;
1560 } else if(isPower() && CHILD(1).representsOdd() && mstruct[0] == CHILD(0) && CHILD(0).representsReal(true)) {
1561 //sgn(x)*x^3=abs(x)^3
1562 CHILD(0).transformById(FUNCTION_ID_ABS);
1563 MERGE_APPROX_AND_PREC(mstruct)
1564 return 1;
1565 }
1566 } else if(mstruct.function()->id() == FUNCTION_ID_ROOT && VALID_ROOT(mstruct)) {
1567 if(equals(mstruct[0]) && mstruct[0].representsReal(true) && mstruct[1].number().isOdd()) {
1568 // root(x, 3)*x=abs(x)^(1/3)*x
1569 mstruct[0].transformById(FUNCTION_ID_ABS);
1570 mstruct[1].number().recip();
1571 mstruct.setType(STRUCT_POWER);
1572 transform(STRUCT_FUNCTION);
1573 setFunctionId(FUNCTION_ID_ABS);
1574 mstruct.ref();
1575 multiply_nocopy(&mstruct);
1576 calculateMultiplyLast(eo);
1577 return 1;
1578 } else if(isPower() && CHILD(1).representsOdd() && CHILD(0) == mstruct[0] && CHILD(0).representsReal(true) && mstruct[1].number().isOdd()) {
1579 // root(x, 3)*x^3=abs(x)^(1/3)*x^3
1580 mstruct[0].transformById(FUNCTION_ID_ABS);
1581 mstruct[1].number().recip();
1582 mstruct.setType(STRUCT_POWER);
1583 CHILD(0).transformById(FUNCTION_ID_ABS);
1584 mstruct.ref();
1585 multiply_nocopy(&mstruct);
1586 calculateMultiplyLast(eo);
1587 return 1;
1588 } else if(isPower() && CHILD(0).isFunction() && CHILD(0).function()->id() == FUNCTION_ID_ABS && CHILD(0).size() == 1 && CHILD(0)[0].equals(mstruct[0]) && CHILD(1).isNumber() && CHILD(1).number().isRational() && CHILD(1).number().isFraction() && CHILD(1).number().denominator() == mstruct[1].number() && CHILD(0).representsReal(true) && CHILD(1).number().numerator() == mstruct[1].number() - 1) {
1589 // root(x, 3)*abs(x)^(2/3)=x
1590 SET_CHILD_MAP(0)
1591 SET_CHILD_MAP(0)
1592 return 1;
1593 }
1594 } else if(eo.transform_trigonometric_functions && mstruct.function()->id() == FUNCTION_ID_SINC && mstruct.size() == 1 && equals(mstruct[0])) {
1595 // sinc(x)*x=sin(x)
1596 calculateMultiply(CALCULATOR->getRadUnit(), eo);
1597 transformById(FUNCTION_ID_SIN);
1598 if(eo.calculate_functions) calculateFunctions(eo, false);
1599 MERGE_APPROX_AND_PREC(mstruct)
1600 return 1;
1601 }
1602 }
1603 if(isZero()) {
1604 if(mstruct.isFunction()) {
1605 if((mstruct.function()->id() == FUNCTION_ID_LOG || mstruct.function()->id() == FUNCTION_ID_EXPINT) && mstruct.size() == 1) {
1606 if(mstruct[0].representsNonZero() || warn_about_assumed_not_value(mstruct[0], m_zero, eo)) {
1607 // 0*ln(x)=0 and 0*Ei(x)=0 if x is assumed non-zero
1608 MERGE_APPROX_AND_PREC(mstruct)
1609 return 2;
1610 }
1611 } else if(mstruct.function()->id() == FUNCTION_ID_LOGINT && mstruct.size() == 1) {
1612 if(mstruct.representsNumber(true) || warn_about_assumed_not_value(mstruct[0], m_one, eo)) {
1613 // 0*li(x)=0 if x is assumed not one
1614 MERGE_APPROX_AND_PREC(mstruct)
1615 return 2;
1616 }
1617 } else if(mstruct.function()->id() == FUNCTION_ID_TAN && mstruct.size() == 1) {
1618 mstruct.setFunctionId(FUNCTION_ID_COS);
1619 if(warn_about_assumed_not_value(mstruct, m_zero, eo)) {
1620 // 0*tan(x)=0 if cos(x) != 0
1621 MERGE_APPROX_AND_PREC(mstruct)
1622 return 2;
1623 }
1624 mstruct.setFunctionId(FUNCTION_ID_TAN);
1625 }
1626 } else if(mstruct.isPower() && mstruct[0].isFunction() && mstruct[1].representsNumber()) {
1627 if((mstruct[0].function()->id() == FUNCTION_ID_LOG || mstruct[0].function()->id() == FUNCTION_ID_EXPINT) && mstruct[0].size() == 1) {
1628 if(mstruct[0][0].representsNonZero() || warn_about_assumed_not_value(mstruct[0][0], m_zero, eo)) {
1629 // ln(x)^a*0=0 and Ei(x)*0=0 if x is assumed non-zero
1630 MERGE_APPROX_AND_PREC(mstruct)
1631 return 2;
1632 }
1633 } else if(mstruct[0].function()->id() == FUNCTION_ID_LOGINT && mstruct[0].size() == 1) {
1634 if(mstruct[0].representsNumber(true) || warn_about_assumed_not_value(mstruct[0][0], m_one, eo)) {
1635 // li(x)^a*0=0 if x is assumed not one
1636 MERGE_APPROX_AND_PREC(mstruct)
1637 return 2;
1638 }
1639 } else if(mstruct[0].function()->id() == FUNCTION_ID_TAN && mstruct[0].size() == 1) {
1640 mstruct[0].setFunctionId(FUNCTION_ID_COS);
1641 if(warn_about_assumed_not_value(mstruct[0], m_zero, eo)) {
1642 // 0*tan(x)^a=0 if cos(x) != 0
1643 MERGE_APPROX_AND_PREC(mstruct)
1644 return 2;
1645 }
1646 mstruct[0].setFunctionId(FUNCTION_ID_TAN);
1647 }
1648 }
1649 }
1650
1651 switch(m_type) {
1652 case STRUCT_VECTOR: {
1653 switch(mstruct.type()) {
1654 case STRUCT_ADDITION: {
1655 return 0;
1656 }
1657 case STRUCT_VECTOR: {
1658 if(isMatrix() && mstruct.isMatrix()) {
1659 // matrix multiplication
1660 // the number of columns in the first matrix must be equal to the number of rows in the second matrix
1661 if(CHILD(0).size() != mstruct.size()) {
1662 CALCULATOR->error(true, _("The second matrix must have as many rows (was %s) as the first has columns (was %s) for matrix multiplication."), i2s(mstruct.size()).c_str(), i2s(CHILD(0).size()).c_str(), NULL);
1663 return -1;
1664 }
1665 MathStructure msave(*this);
1666 size_t rows = SIZE;
1667 clearMatrix(true);
1668 resizeMatrix(rows, mstruct[0].size(), m_zero);
1669 MathStructure mtmp;
1670 for(size_t index_r = 0; index_r < SIZE; index_r++) {
1671 for(size_t index_c = 0; index_c < CHILD(0).size(); index_c++) {
1672 for(size_t index = 0; index < msave[0].size(); index++) {
1673 mtmp = msave[index_r][index];
1674 mtmp.calculateMultiply(mstruct[index][index_c], eo);
1675 CHILD(index_r)[index_c].calculateAdd(mtmp, eo, &CHILD(index_r), index_c);
1676 }
1677 }
1678 }
1679 MERGE_APPROX_AND_PREC(mstruct)
1680 return 1;
1681 } else if(isMatrix() && mstruct.isVector()) {
1682 // matrix multiplication (vector is treated as matrix with 1 column)
1683 if(CHILD(0).size() != mstruct.size()) {
1684 CALCULATOR->error(true, _("The second matrix must have as many rows (was %s) as the first has columns (was %s) for matrix multiplication."), i2s(1).c_str(), i2s(CHILD(0).size()).c_str(), NULL);
1685 return -1;
1686 }
1687 MathStructure msave(*this);
1688 size_t rows = SIZE;
1689 clearMatrix(true);
1690 resizeMatrix(rows, 1, m_zero);
1691 MathStructure mtmp;
1692 for(size_t index_r = 0; index_r < SIZE; index_r++) {
1693 for(size_t index_c = 0; index_c < msave[0].size(); index_c++) {
1694 mtmp = msave[index_r][index_c];
1695 mtmp.calculateMultiply(mstruct[index_c], eo);
1696 CHILD(index_r)[0].calculateAdd(mtmp, eo, &CHILD(index_r), 0);
1697 }
1698 }
1699 MERGE_APPROX_AND_PREC(mstruct)
1700 return 1;
1701 } else {
1702 // dot product of two vectors: [a1, a2, a3, ..]*[b1, b2, b3, ...]=a1*b1+a2*b2+a3*b3+...
1703 // dimension of the vectors must be equal
1704 if(SIZE == mstruct.size()) {
1705 if(SIZE == 0) {clear(true); return 1;}
1706 for(size_t i = 0; i < SIZE; i++) {
1707 mstruct[i].ref();
1708 CHILD(i).multiply_nocopy(&mstruct[i], true);
1709 CHILD(i).calculateMultiplyLast(eo, true);
1710 }
1711 m_type = STRUCT_ADDITION;
1712 MERGE_APPROX_AND_PREC(mstruct)
1713 calculatesub(eo, eo, false, mparent, index_this);
1714 return 1;
1715 }
1716 }
1717 return -1;
1718 }
1719 default: {
1720 if(!mstruct.representsScalar()) return -1;
1721 // matrix/vector multiplied by scalar: multiply each element
1722 for(size_t i = 0; i < SIZE; i++) {
1723 CHILD(i).calculateMultiply(mstruct, eo);
1724 }
1725 MERGE_APPROX_AND_PREC(mstruct)
1726 calculatesub(eo, eo, false, mparent, index_this);
1727 return 1;
1728 }
1729 }
1730 }
1731 case STRUCT_ADDITION: {
1732 if(eo.expand != 0 && containsType(STRUCT_DATETIME, false, true, false) > 0) return -1;
1733 switch(mstruct.type()) {
1734 case STRUCT_ADDITION: {
1735 // multiplication of polynomials
1736 // avoid multiplication of very long polynomials
1737 if(eo.expand != 0 && SIZE < 1000 && mstruct.size() < 1000 && (SIZE * mstruct.size() < (eo.expand == -1 ? 50 : 500))) {
1738 // avoid multiplication of polynomials with intervals (if factors might be negitive)
1739 if(eo.expand > -2 || (!containsInterval(true, false, false, eo.expand == -2 ? 1 : 0) && !mstruct.containsInterval(true, false, false, eo.expand == -2 ? 1 : 0)) || (representsNonNegative(true) && mstruct.representsNonNegative(true))) {
1740 MathStructure msave(*this);
1741 CLEAR;
1742 for(size_t i = 0; i < mstruct.size(); i++) {
1743 if(CALCULATOR->aborted()) {
1744 set(msave);
1745 return -1;
1746 }
1747 APPEND(msave);
1748 mstruct[i].ref();
1749 LAST.multiply_nocopy(&mstruct[i], true);
1750 if(reversed) {
1751 LAST.swapChildren(1, LAST.size());
1752 LAST.calculateMultiplyIndex(0, eo, true, this, SIZE - 1);
1753 } else {
1754 LAST.calculateMultiplyLast(eo, true, this, SIZE - 1);
1755 }
1756 }
1757 MERGE_APPROX_AND_PREC(mstruct)
1758 calculatesub(eo, eo, false, mparent, index_this);
1759 return 1;
1760 } else if(eo.expand <= -2 && (!mstruct.containsInterval(true, false, false, eo.expand == -2 ? 1 : 0) || representsNonNegative(true))) {
1761 for(size_t i = 0; i < SIZE; i++) {
1762 CHILD(i).calculateMultiply(mstruct, eo, this, i);
1763 }
1764 calculatesub(eo, eo, false, mparent, index_this);
1765 return 1;
1766 } else if(eo.expand <= -2 && (!containsInterval(true, false, false, eo.expand == -2 ? 1 : 0) || mstruct.representsNonNegative(true))) {
1767 return 0;
1768 }
1769 }
1770 if(equals(mstruct)) {
1771 // x*x=x^2
1772 raise_nocopy(new MathStructure(2, 1, 0));
1773 MERGE_APPROX_AND_PREC(mstruct)
1774 return 1;
1775 }
1776 break;
1777 }
1778 case STRUCT_POWER: {
1779 if(mstruct[1].isNumber() && *this == mstruct[0]) {
1780 // (x+y)(x+y)^a=(x+y)^(a+1)
1781 // check if a might be -1 and (x+y) might be zero
1782 if((!eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !representsZero(true))
1783 || (mstruct[1].isNumber() && mstruct[1].number().isReal() && !mstruct[1].number().isMinusOne())
1784 || representsNonZero(true)
1785 || mstruct[1].representsPositive()
1786 || (eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !representsZero(true) && warn_about_denominators_assumed_nonzero_or_positive(*this, mstruct[1], eo))) {
1787 if(mparent) {
1788 mparent->swapChildren(index_this + 1, index_mstruct + 1);
1789 (*mparent)[index_this][1].number()++;
1790 (*mparent)[index_this].calculateRaiseExponent(eo, mparent, index_this);
1791 } else {
1792 set_nocopy(mstruct, true);
1793 CHILD(1).number()++;
1794 calculateRaiseExponent(eo, mparent, index_this);
1795 }
1796 return 1;
1797 }
1798 }
1799 if(eo.expand == 0 && mstruct[0].isAddition()) return -1;
1800 // eo.combine_divisions is not used anymore
1801 if(eo.combine_divisions && mstruct[1].hasNegativeSign()) {
1802 int ret;
1803 vector<bool> merged;
1804 merged.resize(SIZE, false);
1805 size_t merges = 0;
1806 MathStructure *mstruct2 = new MathStructure(mstruct);
1807 for(size_t i = 0; i < SIZE; i++) {
1808 if(CHILD(i).isOne()) ret = -1;
1809 else ret = CHILD(i).merge_multiplication(*mstruct2, eo, NULL, 0, 0, false, false);
1810 if(ret == 0) {
1811 ret = mstruct2->merge_multiplication(CHILD(i), eo, NULL, 0, 0, true, false);
1812 if(ret >= 1) {
1813 mstruct2->ref();
1814 setChild_nocopy(mstruct2, i + 1);
1815 }
1816 }
1817 if(ret >= 1) {
1818 mstruct2->unref();
1819 if(i + 1 != SIZE) mstruct2 = new MathStructure(mstruct);
1820 merged[i] = true;
1821 merges++;
1822 } else {
1823 if(i + 1 == SIZE) mstruct2->unref();
1824 merged[i] = false;
1825 }
1826 }
1827 if(merges == 0) {
1828 return -1;
1829 } else if(merges == SIZE) {
1830 calculatesub(eo, eo, false, mparent, index_this);
1831 return 1;
1832 } else if(merges == SIZE - 1) {
1833 for(size_t i = 0; i < SIZE; i++) {
1834 if(!merged[i]) {
1835 mstruct.ref();
1836 CHILD(i).multiply_nocopy(&mstruct, true);
1837 break;
1838 }
1839 }
1840 calculatesub(eo, eo, false, mparent, index_this);
1841 } else {
1842 MathStructure *mdiv = new MathStructure();
1843 merges = 0;
1844 for(size_t i = 0; i - merges < SIZE; i++) {
1845 if(!merged[i]) {
1846 CHILD(i - merges).ref();
1847 if(merges > 0) {
1848 (*mdiv)[0].add_nocopy(&CHILD(i - merges), merges > 1);
1849 } else {
1850 mdiv->multiply(mstruct);
1851 mdiv->setChild_nocopy(&CHILD(i - merges), 1);
1852 }
1853 ERASE(i - merges);
1854 merges++;
1855 }
1856 }
1857 add_nocopy(mdiv, true);
1858 calculatesub(eo, eo, false);
1859 }
1860 return 1;
1861 }
1862 if(eo.expand == 0 || (eo.expand < -1 && mstruct.containsInterval(true, false, false, eo.expand == -2 ? 1 : 0) && !representsNonNegative(true))) return -1;
1863 }
1864 case STRUCT_MULTIPLICATION: {
1865 if(do_append && (eo.expand == 0 || (eo.expand < -1 && mstruct.containsInterval(true, false, false, eo.expand == -2 ? 1 : 0) && !representsNonNegative(true)))) {
1866 transform(STRUCT_MULTIPLICATION);
1867 for(size_t i = 0; i < mstruct.size(); i++) {
1868 APPEND_REF(&mstruct[i]);
1869 }
1870 return 1;
1871 }
1872 }
1873 default: {
1874 if(eo.expand == 0 || (eo.expand < -1 && mstruct.containsInterval(true, false, false, eo.expand == -2 ? 1 : 0) && !representsNonNegative(true))) return -1;
1875 // (a1+a2+...)*b=(ba1+ba2+...)
1876 for(size_t i = 0; i < SIZE; i++) {
1877 CHILD(i).multiply(mstruct, true);
1878 if(reversed) {
1879 CHILD(i).swapChildren(1, CHILD(i).size());
1880 CHILD(i).calculateMultiplyIndex(0, eo, true, this, i);
1881 } else {
1882 CHILD(i).calculateMultiplyLast(eo, true, this, i);
1883 }
1884 }
1885 MERGE_APPROX_AND_PREC(mstruct)
1886 calculatesub(eo, eo, false, mparent, index_this);
1887 return 1;
1888 }
1889 }
1890 return -1;
1891 }
1892 case STRUCT_MULTIPLICATION: {
1893 switch(mstruct.type()) {
1894 case STRUCT_VECTOR: {}
1895 case STRUCT_ADDITION: {
1896 if(eo.expand == 0 || containsType(STRUCT_DATETIME, false, true, false) > 0) {
1897 if(!do_append) return -1;
1898 APPEND_REF(&mstruct);
1899 return 1;
1900 }
1901 // try again with reversed order
1902 return 0;
1903 }
1904 case STRUCT_MULTIPLICATION: {
1905 // (a1*a2*...)(b1*b2*...)=a1*a2*...*b1*b2*...
1906 for(size_t i = 0; i < mstruct.size(); i++) {
1907 if(reversed) {
1908 PREPEND_REF(&mstruct[i]);
1909 calculateMultiplyIndex(0, eo, false);
1910 } else {
1911 APPEND_REF(&mstruct[i]);
1912 calculateMultiplyLast(eo, false);
1913 }
1914 }
1915 MERGE_APPROX_AND_PREC(mstruct)
1916 if(SIZE == 1) {
1917 setToChild(1, false, mparent, index_this + 1);
1918 } else if(SIZE == 0) {
1919 clear(true);
1920 } else {
1921 evalSort();
1922 }
1923 return 1;
1924 }
1925 case STRUCT_POWER: {
1926 if(mstruct[1].isNumber() && equals(mstruct[0])) {
1927 // xy(xy)^a=(xy)^(a+1)
1928 // check if a might be -1 and xy might be zero
1929 if((!eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !representsZero(true))
1930 || (mstruct[1].isNumber() && mstruct[1].number().isReal() && !mstruct[1].number().isMinusOne())
1931 || representsNonZero(true)
1932 || mstruct[1].representsPositive()
1933 || (eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !representsZero(true) && warn_about_denominators_assumed_nonzero_or_positive(*this, mstruct[1], eo))) {
1934 if(mparent) {
1935 mparent->swapChildren(index_this + 1, index_mstruct + 1);
1936 (*mparent)[index_this][1].number()++;
1937 (*mparent)[index_this].calculateRaiseExponent(eo, mparent, index_this);
1938 } else {
1939 set_nocopy(mstruct, true);
1940 CHILD(1).number()++;
1941 calculateRaiseExponent(eo, mparent, index_this);
1942 }
1943 return 1;
1944 }
1945 }
1946 }
1947 default: {
1948 if(do_append) {
1949 MERGE_APPROX_AND_PREC(mstruct)
1950 if(reversed) {
1951 PREPEND_REF(&mstruct);
1952 calculateMultiplyIndex(0, eo, true, mparent, index_this);
1953 } else {
1954 APPEND_REF(&mstruct);
1955 calculateMultiplyLast(eo, true, mparent, index_this);
1956 }
1957 return 1;
1958 } else {
1959 for(size_t i = 0; i < SIZE; i++) {
1960 int ret = CHILD(i).merge_multiplication(mstruct, eo, NULL, 0, 0, false, false);
1961 if(ret == 0) {
1962 ret = mstruct.merge_multiplication(CHILD(i), eo, NULL, 0, 0, true, false);
1963 if(ret >= 1) {
1964 if(ret == 2) ret = 3;
1965 else if(ret == 3) ret = 2;
1966 mstruct.ref();
1967 setChild_nocopy(&mstruct, i + 1);
1968 }
1969 }
1970 if(ret >= 1) {
1971 if(ret != 2) calculateMultiplyIndex(i, eo, true, mparent, index_this);
1972 return 1;
1973 }
1974 }
1975 }
1976 }
1977 }
1978 return -1;
1979 }
1980 case STRUCT_POWER: {
1981 switch(mstruct.type()) {
1982 case STRUCT_VECTOR: {}
1983 case STRUCT_ADDITION: {}
1984 case STRUCT_MULTIPLICATION: {
1985 // try again with reversed order
1986 return 0;
1987 }
1988 case STRUCT_POWER: {
1989 if(CHILD(0).isFunction() && CHILD(0).function()->id() == FUNCTION_ID_ABS && mstruct[0].isFunction() && mstruct[0].function()->id() == FUNCTION_ID_ROOT && mstruct[1].isMinusOne() && CHILD(0).size() == 1 && VALID_ROOT(mstruct[0]) && CHILD(0)[0].equals(mstruct[0][0]) && CHILD(1).isNumber() && CHILD(1).number().isRational() && CHILD(1).number().isFraction() && CHILD(1).number().denominator() == mstruct[0][1].number() && CHILD(0)[0].representsReal(true) && CHILD(1).number().numerator() == -(mstruct[0][1].number() - 1)) {
1990 // root(x, 3)^-1*abs(x)^(-2/3)=1/x
1991 SET_CHILD_MAP(0)
1992 SET_CHILD_MAP(0)
1993 raise(m_minus_one);
1994 return 1;
1995 }
1996 if(mstruct[0].isFunction() && mstruct[0].function()->id() == FUNCTION_ID_ABS && CHILD(0).isFunction() && CHILD(0).function()->id() == FUNCTION_ID_ROOT && CHILD(1).isMinusOne() && mstruct[0].size() == 1 && VALID_ROOT(CHILD(0)) && CHILD(0)[0].equals(mstruct[0][0]) && mstruct[1].isNumber() && mstruct[1].number().isRational() && mstruct[1].number().isFraction() && mstruct[1].number().denominator() == CHILD(0)[1].number() && mstruct[0][0].representsReal(true) && mstruct[1].number().numerator() == -(CHILD(0)[1].number() - 1)) {
1997 // root(x, 3)^-1*abs(x)^(-2/3)=1/x
1998 SET_CHILD_MAP(0)
1999 SET_CHILD_MAP(0)
2000 raise(m_minus_one);
2001 return 1;
2002 }
2003 if(mstruct[0] == CHILD(0) || (CHILD(0).isMultiplication() && CHILD(0).size() == 2 && CHILD(0)[0].isMinusOne() && CHILD(0)[1] == mstruct[0] && (mstruct[1].representsEven() || mstruct[1].representsOdd()))) {
2004 // x^a*x^b=x^(a+b)
2005 // (-x)^a*x^b=(-x)^(a+b) if b is even
2006 // (-x)^a*x^b=-(-x)^(a+b) if b is odd
2007 if(mstruct[0].isUnit() && mstruct[0].prefix()) {
2008 if(CHILD(0).isMultiplication()) CHILD(0)[0].setPrefix(mstruct[0].prefix());
2009 else CHILD(0).setPrefix(mstruct[0].prefix());
2010 }
2011 bool b = eo.allow_complex || CHILD(0).representsNonNegative(true), b2 = true, b_warn = false;
2012 if(!b) {
2013 // if complex not allowed and base might be negative, exponents must be integers
2014 b = CHILD(1).representsInteger() && mstruct[1].representsInteger();
2015 }
2016 bool b_neg = mstruct[1].representsOdd() && !(mstruct[0] == CHILD(0));
2017 if(b) {
2018 b = false;
2019 bool b2test = false;
2020 if(IS_REAL(mstruct[1]) && IS_REAL(CHILD(1))) {
2021 if(mstruct[1].number().isPositive() == CHILD(1).number().isPositive()) {
2022 b2 = true;
2023 b = true;
2024 } else if(!mstruct[1].number().isMinusOne() && !CHILD(1).number().isMinusOne()) {
2025 b2 = (mstruct[1].number() + CHILD(1).number()).isNegative();
2026 b = true;
2027 if(!b2) {
2028 // sign of exponent changes: test if base is non-zero
2029 b2test = true;
2030 }
2031 }
2032 }
2033 if(!b || b2test) {
2034 b = (!eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !CHILD(0).representsZero(true))
2035 || CHILD(0).representsNonZero(true)
2036 || (CHILD(1).representsPositive() && mstruct[1].representsPositive())
2037 || (CHILD(1).representsNegative() && mstruct[1].representsNegative());
2038 if(!b && eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !CHILD(0).representsZero(true)) {
2039 b = true;
2040 b_warn = true;
2041 }
2042 if(b2test) {
2043 b2 = b;
2044 if(!b_neg) b = true;
2045 } else if(b_neg) {
2046 b = false;
2047 }
2048 }
2049 }
2050 if(b) {
2051 if(IS_REAL(CHILD(1)) && IS_REAL(mstruct[1])) {
2052 // exponents are real numbers
2053 if(!b2 && !do_append) return -1;
2054 // test if base is non-zero (if exponent is negative)
2055 if(b_warn && !warn_about_denominators_assumed_nonzero(CHILD(0), eo)) return -1;
2056 if(b2) {
2057 // exponents can safely be combined
2058 CHILD(1).number() += mstruct[1].number();
2059 if(b_neg) {
2060 calculateRaiseExponent(eo);
2061 calculateNegate(eo, mparent, index_this);
2062 } else {
2063 calculateRaiseExponent(eo, mparent, index_this);
2064 }
2065 } else {
2066 // a and b have different signs and a+b is not negative: x^a/x^b=x^(a-b+1)/x
2067 if(CHILD(1).number().isNegative()) {
2068 CHILD(1).number()++;
2069 mstruct[1].number() += CHILD(1).number();
2070 CHILD(1).number().set(-1, 1, 0);
2071 } else {
2072 mstruct[1].number()++;
2073 CHILD(1).number() += mstruct[1].number();
2074 mstruct[1].number().set(-1, 1, 0);
2075 }
2076 MERGE_APPROX_AND_PREC(mstruct)
2077 transform(STRUCT_MULTIPLICATION);
2078 CHILD(0).calculateRaiseExponent(eo, this, 0);
2079 if(reversed) {
2080 PREPEND_REF(&mstruct);
2081 CHILD(0).calculateRaiseExponent(eo, this, 0);
2082 calculateMultiplyIndex(0, eo, true, mparent, index_this);
2083 } else {
2084 APPEND_REF(&mstruct);
2085 CHILD(1).calculateRaiseExponent(eo, this, 1);
2086 calculateMultiplyLast(eo, true, mparent, index_this);
2087 }
2088 }
2089 return 1;
2090 } else {
2091 if(CHILD(0).isNumber() && CHILD(0).number().isRational() && !CHILD(0).number().isZero()) {
2092 // avoid endless loop (e.g. a^(2/3*x)/a^x)
2093 bool b1n = false, b1m = false;
2094 bool b2n = false, b2m = false;
2095 if(CHILD(1).isMultiplication() && CHILD(1).size() > 0) {
2096 if(mstruct[1].isMultiplication() && mstruct[1].size() > 0) {
2097 size_t i1 = 0, i2 = 0;
2098 if(CHILD(1)[0].isNumber()) i1 = 1;
2099 if(mstruct[1][0].isNumber()) i2 = 1;
2100 if((i1 || i2) && SIZE - i1 == mstruct[1].size() - i2) {
2101 b1n = true;
2102 for(size_t i = i1; i < SIZE; i++) {
2103 if(CHILD(1)[i] != mstruct[1][i + i2 - i1]) {
2104 b1n = false;
2105 break;
2106 }
2107 }
2108 }
2109 if(b1n) {
2110 b1m = (i1 == 1 && CHILD(1)[0].number().isMinusOne());
2111 b1n = (!b1m && i1 == 1 && CHILD(1)[0].number().isRational() && CHILD(1)[0].number().isFraction());
2112 b2m = (i2 == 1 && mstruct[1][0].number().isMinusOne());
2113 b2n = (!b2m && i2 == 1 && mstruct[1][0].number().isRational() && mstruct[1][0].number().isFraction());
2114 }
2115 } else if(CHILD(1).size() == 2 && CHILD(1)[0].isNumber() && CHILD(1)[0].number().isFraction() && CHILD(1)[0].number().isRational() && CHILD(1)[0].number().isNegative() && CHILD(1)[1] == mstruct[1]) {
2116 b1n = true;
2117 }
2118 } else if(mstruct[1].isMultiplication() && mstruct[1].size() == 2 && mstruct[1][0].isNumber() && mstruct[1][0].number().isRational() && mstruct[1][0].number().isFraction() && mstruct[1][0].number().isNegative() && mstruct[1][1] == CHILD(1)) {
2119 b2n = true;
2120 }
2121 if(b1n && !b2m && !b2n) {
2122 if(cmp_num_abs_2_to_den(CHILD(1)[0].number()) < 0) return -1;
2123 } else if(b2n && !b1m && !b1n) {
2124 if(cmp_num_abs_2_to_den(mstruct[1][0].number()) < 0) return -1;
2125 } else if(b1n && b2m && CHILD(1)[0].number().isPositive()) {
2126 if(cmp_num_abs_2_to_den(CHILD(1)[0].number()) <= 0) return -1;
2127 } else if(b2n && b1m && mstruct[1][0].number().isPositive()) {
2128 if(cmp_num_abs_2_to_den(mstruct[1][0].number()) <= 0) return -1;
2129 }
2130 }
2131 MathStructure mstruct2(CHILD(1));
2132 if(mstruct2.calculateAdd(mstruct[1], eo)) {
2133 // test and warn for possible division by zero (test both base and exponents)
2134 if(b_warn && !warn_about_denominators_assumed_nonzero_llgg(CHILD(0), CHILD(1), mstruct[1], eo)) return -1;
2135 CHILD(1) = mstruct2;
2136 calculateRaiseExponent(eo, mparent, index_this);
2137 return 1;
2138 }
2139 }
2140 }
2141 } else if(mstruct[1] == CHILD(1)) {
2142 if(!CHILD(0).isMultiplication() && !mstruct[0].isMultiplication() && (mstruct[1].representsInteger() || CHILD(0).representsPositive(true) || mstruct[0].representsPositive(true))) {
2143 // x^a*y^a=(xy)^a if x and y is positive, or a is integer
2144 MathStructure mstruct2(CHILD(0));
2145 if(mstruct2.calculateMultiply(mstruct[0], eo)) {
2146 CHILD(0) = mstruct2;
2147 MERGE_APPROX_AND_PREC(mstruct)
2148 calculateRaiseExponent(eo, mparent, index_this);
2149 return 1;
2150 }
2151 } else if(eo.transform_trigonometric_functions && CHILD(1).representsInteger() && CHILD(0).isFunction() && mstruct[0].isFunction() && eo.protected_function != mstruct[0].function() && eo.protected_function != CHILD(0).function() && CHILD(0).size() == 1 && mstruct[0].size() == 1 && CHILD(0)[0] == mstruct[0][0]) {
2152 if((CHILD(0).function()->id() == FUNCTION_ID_COS && mstruct[0].function()->id() == FUNCTION_ID_SIN) || (CHILD(0).function()->id() == FUNCTION_ID_SIN && mstruct[0].function()->id() == FUNCTION_ID_COS) || (CHILD(0).function()->id() == FUNCTION_ID_COSH && mstruct[0].function()->id() == FUNCTION_ID_SINH) || (CHILD(0).function()->id() == FUNCTION_ID_SINH && mstruct[0].function()->id() == FUNCTION_ID_COSH)) {
2153 // cos(x)^n*sin(x)^n=sin(2x)^n/2^n
2154 if(CHILD(0).function()->id() == FUNCTION_ID_COSH) CHILD(0).setFunctionId(FUNCTION_ID_SINH);
2155 else if(CHILD(0).function()->id() == FUNCTION_ID_COS) CHILD(0).setFunctionId(FUNCTION_ID_SIN);
2156 CHILD(0)[0].calculateMultiply(nr_two, eo);
2157 CHILD(0).childUpdated(1);
2158 CHILD_UPDATED(0)
2159 MathStructure *mdiv = new MathStructure(2, 1, 0);
2160 mdiv->calculateRaise(CHILD(1), eo);
2161 mdiv->calculateInverse(eo);
2162 multiply_nocopy(mdiv);
2163 calculateMultiplyLast(eo);
2164 MERGE_APPROX_AND_PREC(mstruct)
2165 return 1;
2166 } else if((CHILD(0).function()->id() == FUNCTION_ID_TAN && mstruct[0].function()->id() == FUNCTION_ID_COS) || (CHILD(0).function()->id() == FUNCTION_ID_COS && mstruct[0].function()->id() == FUNCTION_ID_TAN)) {
2167 // tan(x)^n*cos(x)^n=sin(x)^n
2168 CHILD(0).setFunctionId(FUNCTION_ID_SIN);
2169 MERGE_APPROX_AND_PREC(mstruct)
2170 return 1;
2171 } else if((CHILD(0).function()->id() == FUNCTION_ID_TANH && mstruct[0].function()->id() == FUNCTION_ID_COSH) || (CHILD(0).function()->id() == FUNCTION_ID_COSH && mstruct[0].function()->id() == FUNCTION_ID_TANH)) {
2172 // tanh(x)^n*cosh(x)^n=sinh(x)^n
2173 CHILD(0).setFunctionId(FUNCTION_ID_SIN);
2174 MERGE_APPROX_AND_PREC(mstruct)
2175 return 1;
2176 }
2177 }
2178 } else if(eo.transform_trigonometric_functions && CHILD(1).isInteger() && mstruct[1].isInteger() && CHILD(0).isFunction() && mstruct[0].isFunction() && eo.protected_function != mstruct[0].function() && eo.protected_function != CHILD(0).function() && mstruct[0].size() == 1 && CHILD(0).size() == 1 && CHILD(0)[0] == mstruct[0][0]) {
2179 if(CHILD(1).number().isNonNegative() != mstruct[1].number().isNonNegative()) {
2180 if(CHILD(0).function()->id() == FUNCTION_ID_SIN) {
2181 if(mstruct[0].function()->id() == FUNCTION_ID_COS) {
2182 // sin(x)^n/cos(x)^m=tan(x)^n if n=m
2183 // sin(x)^n/cos(x)^m=tan(x)^m*sin(x)^(n-m) if n>m
2184 // sin(x)^n/cos(x)^m=tan(x)^m/cos(x)^(m-n) if n<m
2185 CHILD(0).setFunctionId(FUNCTION_ID_TAN);
2186 mstruct[1].number() += CHILD(1).number();
2187 if(mstruct[1].number().isZero()) {
2188 // n=m
2189 MERGE_APPROX_AND_PREC(mstruct)
2190 return 1;
2191 } else if(mstruct[1].number().isPositive() == CHILD(1).number().isPositive()) {
2192 // n>m
2193 mstruct[0].setFunctionId(FUNCTION_ID_SIN);
2194 CHILD(1).number() -= mstruct[1].number();
2195 }
2196 mstruct.ref();
2197 multiply_nocopy(&mstruct);
2198 calculateMultiplyLast(eo);
2199 return 1;
2200 } else if(mstruct[0].function()->id() == FUNCTION_ID_TAN) {
2201 // sin(x)^n/tan(x)^m=cos(x)^n if n=m
2202 // sin(x)^n/tan(x)^m=cos(x)^m*sin(x)^(n-m) if n>m
2203 // sin(x)^n/tan(x)^m=cos(x)^m/tan(x)^(m-n) if n<m
2204 CHILD(0).setFunctionId(FUNCTION_ID_COS);
2205 mstruct[1].number() += CHILD(1).number();
2206 if(mstruct[1].number().isZero()) {
2207 // n=m
2208 MERGE_APPROX_AND_PREC(mstruct)
2209 return 1;
2210 } else if(mstruct[1].number().isPositive() == CHILD(1).number().isPositive()) {
2211 // n>m
2212 mstruct[0].setFunctionId(FUNCTION_ID_SIN);
2213 CHILD(1).number() -= mstruct[1].number();
2214 }
2215 mstruct.ref();
2216 multiply_nocopy(&mstruct);
2217 calculateMultiplyLast(eo);
2218 return 1;
2219 }
2220 } else if(CHILD(0).function()->id() == FUNCTION_ID_COS) {
2221 if(mstruct[0].function()->id() == FUNCTION_ID_SIN) {
2222 // sin(x)^n/cos(x)^m=tan(x)^n if n=m
2223 // sin(x)^n/cos(x)^m=tan(x)^m*sin(x)^(n-m) if n>m
2224 // sin(x)^n/cos(x)^m=tan(x)^m/cos(x)^(m-n) if n<m
2225 mstruct[0].setFunctionId(FUNCTION_ID_TAN);
2226 CHILD(1).number() += mstruct[1].number();
2227 if(CHILD(1).number().isZero()) {
2228 // n=m
2229 set(mstruct, true);
2230 return 1;
2231 } else if(mstruct[1].number().isPositive() == CHILD(1).number().isPositive()) {
2232 // n>m
2233 CHILD(0).setFunctionId(FUNCTION_ID_SIN);
2234 mstruct[1].number() -= CHILD(1).number();
2235 }
2236 mstruct.ref();
2237 multiply_nocopy(&mstruct);
2238 calculateMultiplyLast(eo);
2239 return 1;
2240 }
2241 } else if(CHILD(0).function()->id() == FUNCTION_ID_TAN) {
2242 if(mstruct[0].function()->id() == FUNCTION_ID_SIN) {
2243 // sin(x)^n/tan(x)^m=cos(x)^n if n=m
2244 // sin(x)^n/tan(x)^m=cos(x)^m*sin(x)^(n-m) if n>m
2245 // sin(x)^n/tan(x)^m=cos(x)^m/tan(x)^(m-n) if n<m
2246 mstruct[0].setFunctionId(FUNCTION_ID_COS);
2247 CHILD(1).number() += mstruct[1].number();
2248 if(CHILD(1).number().isZero()) {
2249 // n=m
2250 set(mstruct, true);
2251 return 1;
2252 } else if(mstruct[1].number().isPositive() == CHILD(1).number().isPositive()) {
2253 // n>m
2254 CHILD(0).setFunctionId(FUNCTION_ID_SIN);
2255 mstruct[1].number() -= CHILD(1).number();
2256 }
2257 mstruct.ref();
2258 multiply_nocopy(&mstruct);
2259 calculateMultiplyLast(eo);
2260 return 1;
2261 }
2262 } else if(CHILD(0).function()->id() == FUNCTION_ID_SINH) {
2263 if(mstruct[0].function()->id() == FUNCTION_ID_COSH) {
2264 // sinh(x)^n/cosh(x)^m=tanh(x)^n if n=m
2265 // sinh(x)^n/cosh(x)^m=tanh(x)^m*sinh(x)^(n-m) if n>m
2266 // sinh(x)^n/cosh(x)^m=tanh(x)^m/cosh(x)^(m-n) if n<m
2267 CHILD(0).setFunctionId(FUNCTION_ID_TANH);
2268 mstruct[1].number() += CHILD(1).number();
2269 if(mstruct[1].number().isZero()) {
2270 // n=m
2271 MERGE_APPROX_AND_PREC(mstruct)
2272 return 1;
2273 } else if(mstruct[1].number().isPositive() == CHILD(1).number().isPositive()) {
2274 // n>m
2275 mstruct[0].setFunctionId(FUNCTION_ID_SINH);
2276 CHILD(1).number() -= mstruct[1].number();
2277 }
2278 mstruct.ref();
2279 multiply_nocopy(&mstruct);
2280 calculateMultiplyLast(eo);
2281 return 1;
2282 } else if(mstruct[0].function()->id() == FUNCTION_ID_TANH) {
2283 // sinh(x)^n/tanh(x)^m=cosh(x)^n if n=m
2284 // sinh(x)^n/tanh(x)^m=cosh(x)^m*sinh(x)^(n-m) if n>m
2285 // sinh(x)^n/tanh(x)^m=cosh(x)^m/tanh(x)^(m-n) if n<m
2286 CHILD(0).setFunctionId(FUNCTION_ID_COSH);
2287 mstruct[1].number() += CHILD(1).number();
2288 if(mstruct[1].number().isZero()) {
2289 // n=m
2290 MERGE_APPROX_AND_PREC(mstruct)
2291 return 1;
2292 } else if(mstruct[1].number().isPositive() == CHILD(1).number().isPositive()) {
2293 // n>m
2294 mstruct[0].setFunctionId(FUNCTION_ID_SINH);
2295 CHILD(1).number() -= mstruct[1].number();
2296 }
2297 mstruct.ref();
2298 multiply_nocopy(&mstruct);
2299 calculateMultiplyLast(eo);
2300 return 1;
2301 }
2302 } else if(CHILD(0).function()->id() == FUNCTION_ID_COSH) {
2303 if(mstruct[0].function()->id() == FUNCTION_ID_SINH) {
2304 // sinh(x)^n/cosh(x)^m=tanh(x)^n if n=m
2305 // sinh(x)^n/cosh(x)^m=tanh(x)^m*sinh(x)^(n-m) if n>m
2306 // sinh(x)^n/cosh(x)^m=tanh(x)^m/cosh(x)^(m-n) if n<m
2307 mstruct[0].setFunctionId(FUNCTION_ID_TANH);
2308 CHILD(1).number() += mstruct[1].number();
2309 if(CHILD(1).number().isZero()) {
2310 // n=m
2311 set(mstruct, true);
2312 return 1;
2313 } else if(mstruct[1].number().isPositive() == CHILD(1).number().isPositive()) {
2314 // n>m
2315 CHILD(0).setFunctionId(FUNCTION_ID_SINH);
2316 mstruct[1].number() -= CHILD(1).number();
2317 }
2318 mstruct.ref();
2319 multiply_nocopy(&mstruct);
2320 calculateMultiplyLast(eo);
2321 return 1;
2322 }
2323 } else if(CHILD(0).function()->id() == FUNCTION_ID_TANH) {
2324 if(mstruct[0].function()->id() == FUNCTION_ID_SINH) {
2325 // sinh(x)^n/tanh(x)^m=cosh(x)^n if n=m
2326 // sinh(x)^n/tanh(x)^m=cosh(x)^m*sinh(x)^(n-m) if n>m
2327 // sinh(x)^n/tanh(x)^m=cosh(x)^m/tanh(x)^(m-n) if n<m
2328 mstruct[0].setFunctionId(FUNCTION_ID_COSH);
2329 CHILD(1).number() += mstruct[1].number();
2330 if(CHILD(1).number().isZero()) {
2331 // n=m
2332 set(mstruct, true);
2333 return 1;
2334 } else if(mstruct[1].number().isPositive() == CHILD(1).number().isPositive()) {
2335 // n>m
2336 CHILD(0).setFunctionId(FUNCTION_ID_SINH);
2337 mstruct[1].number() -= CHILD(1).number();
2338 }
2339 mstruct.ref();
2340 multiply_nocopy(&mstruct);
2341 calculateMultiplyLast(eo);
2342 return 1;
2343 }
2344 }
2345 } else {
2346 if((CHILD(0).function()->id() == FUNCTION_ID_TAN && mstruct[0].function()->id() == FUNCTION_ID_COS)) {
2347 // tan(x)^n*cos(x)^m=sin(x)^n*cos(x)^(m-n)
2348 CHILD(0).setFunctionId(FUNCTION_ID_SIN);
2349 mstruct[1].number() -= CHILD(1).number();
2350 mstruct.ref();
2351 multiply_nocopy(&mstruct);
2352 calculateMultiplyLast(eo);
2353 return 1;
2354 } else if((CHILD(0).function()->id() == FUNCTION_ID_COS && mstruct[0].function()->id() == FUNCTION_ID_TAN)) {
2355 // tan(x)^n*cos(x)^m=sin(x)^n*cos(x)^(m-n)
2356 mstruct[0].setFunctionId(FUNCTION_ID_SIN);
2357 CHILD(1).number() -= mstruct[1].number();
2358 mstruct.ref();
2359 multiply_nocopy(&mstruct);
2360 calculateMultiplyLast(eo);
2361 return 1;
2362 } else if((CHILD(0).function()->id() == FUNCTION_ID_TANH && mstruct[0].function()->id() == FUNCTION_ID_COSH)) {
2363 // tanh(x)^n*cosh(x)^m=sinh(x)^n*cosh(x)^(m-n)
2364 CHILD(0).setFunctionId(FUNCTION_ID_SINH);
2365 mstruct[1].number() -= CHILD(1).number();
2366 mstruct.ref();
2367 multiply_nocopy(&mstruct);
2368 calculateMultiplyLast(eo);
2369 return 1;
2370 } else if((CHILD(0).function()->id() == FUNCTION_ID_COSH && mstruct[0].function()->id() == FUNCTION_ID_TANH)) {
2371 // tanh(x)^n*cosh(x)^m=sinh(x)^n*cosh(x)^(m-n)
2372 mstruct[0].setFunctionId(FUNCTION_ID_SINH);
2373 CHILD(1).number() -= mstruct[1].number();
2374 mstruct.ref();
2375 multiply_nocopy(&mstruct);
2376 calculateMultiplyLast(eo);
2377 return 1;
2378 }
2379 }
2380 } else if(mstruct[0].isMultiplication() && mstruct[0].size() == 2 && mstruct[0][0].isMinusOne() && mstruct[0][1] == CHILD(0) && CHILD(1).representsEven()) {
2381 return 0;
2382 }
2383 break;
2384 }
2385 case STRUCT_FUNCTION: {
2386 if(!FUNCTION_PROTECTED(eo, FUNCTION_ID_SIGNUM) && mstruct.function()->id() == FUNCTION_ID_SIGNUM && mstruct.size() == 2 && CHILD(0).isFunction() && CHILD(0).function()->id() == FUNCTION_ID_ABS && CHILD(0).size() == 1 && mstruct[0] == CHILD(0)[0] && CHILD(1).isNumber() && CHILD(1).number().isRational() && CHILD(1).number().numeratorIsOne() && !CHILD(1).number().denominatorIsEven() && CHILD(0)[0].representsReal(true)) {
2387 // sgn(x)*abs(x)^(1/n)=root(x,n) if x is real
2388 setType(STRUCT_FUNCTION);
2389 setFunctionId(FUNCTION_ID_ROOT);
2390 CHILD(0).setToChild(1, true);
2391 CHILD(1).number().recip();
2392 MERGE_APPROX_AND_PREC(mstruct)
2393 return 1;
2394 }
2395 if(eo.transform_trigonometric_functions && CHILD(0).isFunction() && CHILD(0).size() == 1 && mstruct.size() == 1 && CHILD(1).isInteger() && CHILD(1).number().isNegative() && eo.protected_function != mstruct.function() && eo.protected_function != CHILD(0).function()) {
2396 if(CHILD(0).function()->id() == FUNCTION_ID_SIN) {
2397 if(mstruct.function()->id() == FUNCTION_ID_COS && CHILD(0)[0] == mstruct[0]) {
2398 if(CHILD(1).number().isMinusOne()) {
2399 // cos(x)/sin(x)=1/tan(x)
2400 CHILD(0).setFunctionId(FUNCTION_ID_TAN);
2401 MERGE_APPROX_AND_PREC(mstruct)
2402 return 1;
2403 }
2404 // cos(x)/sin(x)^n=1/(sin(x)^(n-1)*tan(x))
2405 mstruct.setFunctionId(FUNCTION_ID_TAN);
2406 mstruct.raise(nr_minus_one);
2407 CHILD(1).number()++;
2408 mstruct.ref();
2409 multiply_nocopy(&mstruct);
2410 calculateMultiplyLast(eo);
2411 return 1;
2412 } else if(mstruct.function()->id() == FUNCTION_ID_TAN && CHILD(0)[0] == mstruct[0]) {
2413 if(CHILD(1).number().isMinusOne()) {
2414 // tan(x)/sin(x)=1/cos(x)
2415 CHILD(0).setFunctionId(FUNCTION_ID_COS);
2416 MERGE_APPROX_AND_PREC(mstruct)
2417 return 1;
2418 }
2419 // tan(x)/sin(x)^n=1/(cos(x)*sin(x)^(n-1))
2420 mstruct.setFunctionId(FUNCTION_ID_COS);
2421 mstruct.raise(nr_minus_one);
2422 CHILD(1).number()++;
2423 mstruct.ref();
2424 multiply_nocopy(&mstruct);
2425 calculateMultiplyLast(eo);
2426 return 1;
2427 }
2428 } else if(CHILD(0).function()->id() == FUNCTION_ID_COS) {
2429 if(mstruct.function()->id() == FUNCTION_ID_SIN && CHILD(0)[0] == mstruct[0]) {
2430 if(CHILD(1).number().isMinusOne()) {
2431 // sin(x)/cos(x)=tan(x)
2432 CHILD(0).setFunctionId(FUNCTION_ID_TAN);
2433 SET_CHILD_MAP(0)
2434 MERGE_APPROX_AND_PREC(mstruct)
2435 return 1;
2436 }
2437 // sin(x)/cos(x)^n=tan(x)/(cos(x)^(n-1))
2438 mstruct.setFunctionId(FUNCTION_ID_TAN);
2439 CHILD(1).number()++;
2440 mstruct.ref();
2441 multiply_nocopy(&mstruct);
2442 calculateMultiplyLast(eo);
2443 return 1;
2444 }
2445 } else if(CHILD(0).function()->id() == FUNCTION_ID_TAN) {
2446 if(mstruct.function()->id() == FUNCTION_ID_SIN && CHILD(0)[0] == mstruct[0]) {
2447 if(CHILD(1).number().isMinusOne()) {
2448 // sin(x)/tan(x)=cos(x)
2449 CHILD(0).setFunctionId(FUNCTION_ID_COS);
2450 SET_CHILD_MAP(0)
2451 MERGE_APPROX_AND_PREC(mstruct)
2452 return 1;
2453 }
2454 // sin(x)/tan(x)^n=cos(x)/(tan(x)^(n-1))
2455 mstruct.setFunctionId(FUNCTION_ID_COS);
2456 CHILD(1).number()++;
2457 mstruct.ref();
2458 multiply_nocopy(&mstruct);
2459 calculateMultiplyLast(eo);
2460 return 1;
2461 }
2462 } else if(CHILD(0).function()->id() == FUNCTION_ID_SINH) {
2463 if(mstruct.function()->id() == FUNCTION_ID_COSH && CHILD(0)[0] == mstruct[0]) {
2464 if(CHILD(1).number().isMinusOne()) {
2465 // cosh(x)/sinh(x)=1/tanh(x)
2466 CHILD(0).setFunctionId(FUNCTION_ID_TANH);
2467 MERGE_APPROX_AND_PREC(mstruct)
2468 return 1;
2469 }
2470 // cosh(x)/sinh(x)^n=1/(sinh(x)^(n-1)*tanh(x))
2471 mstruct.setFunctionId(FUNCTION_ID_TANH);
2472 mstruct.raise(nr_minus_one);
2473 CHILD(1).number()++;
2474 mstruct.ref();
2475 multiply_nocopy(&mstruct);
2476 calculateMultiplyLast(eo);
2477 return 1;
2478 } else if(mstruct.function()->id() == FUNCTION_ID_TANH && CHILD(0)[0] == mstruct[0]) {
2479 if(CHILD(1).number().isMinusOne()) {
2480 // tanh(x)/sinh(x)=1/cosh(x)
2481 CHILD(0).setFunctionId(FUNCTION_ID_COSH);
2482 MERGE_APPROX_AND_PREC(mstruct)
2483 return 1;
2484 }
2485 // tanh(x)/sinh(x)^n=1/(cosh(x)*sinh(x)^(n-1))
2486 mstruct.setFunctionId(FUNCTION_ID_COSH);
2487 mstruct.raise(nr_minus_one);
2488 CHILD(1).number()++;
2489 mstruct.ref();
2490 multiply_nocopy(&mstruct);
2491 calculateMultiplyLast(eo);
2492 return 1;
2493 }
2494 } else if(CHILD(0).function()->id() == FUNCTION_ID_COSH) {
2495 if(mstruct.function()->id() == FUNCTION_ID_SINH && CHILD(0)[0] == mstruct[0]) {
2496 if(CHILD(1).number().isMinusOne()) {
2497 // sinh(x)/cosh(x)=tanh(x)
2498 CHILD(0).setFunctionId(FUNCTION_ID_TANH);
2499 SET_CHILD_MAP(0)
2500 MERGE_APPROX_AND_PREC(mstruct)
2501 return 1;
2502 }
2503 // sinh(x)/cosh(x)^n=tanh(x)/(cosh(x)^(n-1))
2504 mstruct.setFunctionId(FUNCTION_ID_TANH);
2505 CHILD(1).number()++;
2506 mstruct.ref();
2507 multiply_nocopy(&mstruct);
2508 calculateMultiplyLast(eo);
2509 return 1;
2510 }
2511 } else if(CHILD(0).function()->id() == FUNCTION_ID_TANH) {
2512 if(mstruct.function()->id() == FUNCTION_ID_SINH && CHILD(0)[0] == mstruct[0]) {
2513 if(CHILD(1).number().isMinusOne()) {
2514 // sinh(x)/tanh(x)=cosh(x)
2515 CHILD(0).setFunctionId(FUNCTION_ID_COSH);
2516 SET_CHILD_MAP(0)
2517 MERGE_APPROX_AND_PREC(mstruct)
2518 return 1;
2519 }
2520 // sinh(x)/tanh(x)^n=cosh(x)/(tanh(x)^(n-1))
2521 mstruct.setFunctionId(FUNCTION_ID_COSH);
2522 CHILD(1).number()++;
2523 mstruct.ref();
2524 multiply_nocopy(&mstruct);
2525 calculateMultiplyLast(eo);
2526 return 1;
2527 }
2528 }
2529 }
2530 if(mstruct.function()->id() == FUNCTION_ID_STRIP_UNITS && mstruct.size() == 1) {
2531 if(m_type == STRUCT_POWER && CHILD(0).isVariable() && CHILD(0).variable()->isKnown() && mstruct[0].contains(CHILD(0), false) > 0) {
2532 // v^a*nounit(v)=nounit(v)*(nounit(v)*(units in v))^a
2533 // try extracting units from variable
2534 if(separate_unit_vars(CHILD(0), eo, false)) {
2535 calculateRaiseExponent(eo);
2536 mstruct.ref();
2537 multiply_nocopy(&mstruct);
2538 calculateMultiplyLast(eo);
2539 return 1;
2540 }
2541 }
2542 }
2543 }
2544 default: {
2545 if(!mstruct.isNumber() && CHILD(1).isNumber() && CHILD(0) == mstruct) {
2546 // x*x^a=x^(a+1)
2547 // test if x is non-zero or a is non-negative
2548 if((!eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !CHILD(0).representsZero(true))
2549 || (CHILD(1).isNumber() && CHILD(1).number().isReal() && !CHILD(1).number().isMinusOne())
2550 || CHILD(0).representsNonZero(true)
2551 || CHILD(1).representsPositive()
2552 || (eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !CHILD(0).representsZero(true) && warn_about_denominators_assumed_nonzero_or_positive(CHILD(0), CHILD(1), eo))) {
2553 CHILD(1).number()++;
2554 MERGE_APPROX_AND_PREC(mstruct)
2555 calculateRaiseExponent(eo, mparent, index_this);
2556 return 1;
2557 }
2558 }
2559 // x^a*0=0 (keep units and check if not matrix and not undefined)
2560 if(mstruct.isZero() && (!eo.keep_zero_units || containsType(STRUCT_UNIT, false, true, true) <= 0 || (CHILD(0).isUnit() && CHILD(0).unit() == CALCULATOR->getRadUnit()) || (CHILD(0).isFunction() && CHILD(0).representsNumber(false))) && !representsUndefined(true, true, !eo.assume_denominators_nonzero) && representsNonMatrix()) {
2561 clear(true);
2562 MERGE_APPROX_AND_PREC(mstruct)
2563 return 1;
2564 }
2565 if(CHILD(0).isFunction() && mstruct.isZero() && CHILD(1).representsNumber()) {
2566 if((CHILD(0).function()->id() == FUNCTION_ID_LOG || CHILD(0).function()->id() == FUNCTION_ID_EXPINT) && SIZE == 1) {
2567 if(CHILD(0)[0].representsNonZero() || warn_about_assumed_not_value(CHILD(0)[0], m_zero, eo)) {
2568 // ln(x)^a*0=0 and Ei(x)*0=0 if x is assumed non-zero
2569 clear(true);
2570 MERGE_APPROX_AND_PREC(mstruct)
2571 return 3;
2572 }
2573 } else if(CHILD(0).function()->id() == FUNCTION_ID_LOGINT && SIZE == 1) {
2574 if(CHILD(0).representsNumber(true) || warn_about_assumed_not_value(CHILD(0)[0], m_one, eo)) {
2575 // li(x)^a*0=0 if x is assumed not one
2576 clear(true);
2577 MERGE_APPROX_AND_PREC(mstruct)
2578 return 3;
2579 }
2580 } else if(CHILD(0).function()->id() == FUNCTION_ID_TAN && CHILD(0).size() == 1) {
2581 CHILD(0).setFunctionId(FUNCTION_ID_COS);
2582 if(warn_about_assumed_not_value(CHILD(0), m_zero, eo)) {
2583 // tan(x)^a*0=0 if cos(x) is assumed non-zero
2584 clear(true);
2585 MERGE_APPROX_AND_PREC(mstruct)
2586 return 3;
2587 }
2588 CHILD(0).setFunctionId(FUNCTION_ID_TAN);
2589 }
2590 }
2591 break;
2592 }
2593 }
2594 return -1;
2595 }
2596 case STRUCT_FUNCTION: {
2597 if(eo.protected_function != o_function) {
2598 if(((o_function->id() == FUNCTION_ID_ABS && SIZE == 1 && CHILD(0).isFunction() && CHILD(0).function()->id() == FUNCTION_ID_SIGNUM && CHILD(0).size() == 2) || (o_function->id() == FUNCTION_ID_SIGNUM && SIZE == 2 && CHILD(0).isFunction() && CHILD(0).function()->id() == FUNCTION_ID_ABS && CHILD(0).size() == 1)) && (CHILD(0)[0] == mstruct || (mstruct.isFunction() && mstruct.function()->id() == FUNCTION_ID_ABS && mstruct.size() == 1 && CHILD(0)[0] == mstruct[0]) || (mstruct.isPower() && mstruct[0] == CHILD(0)[0]) || (mstruct.isPower() && mstruct[0].isFunction() && mstruct[0].function()->id() == FUNCTION_ID_ABS && mstruct[0].size() == 1 && CHILD(0)[0] == mstruct[0][0]))) {
2599 // sgn(abs(x))*x^y=x^y
2600 if(mparent) {
2601 mparent->swapChildren(index_this + 1, index_mstruct + 1);
2602 } else {
2603 set_nocopy(mstruct, true);
2604 }
2605 return 3;
2606 } else if(o_function->id() == FUNCTION_ID_ABS && SIZE == 1) {
2607 if(mstruct.isFunction() && mstruct.function()->id() == FUNCTION_ID_ABS && mstruct.size() == 1 && mstruct[0] == CHILD(0) && CHILD(0).representsReal(true)) {
2608 // abs(x)*abs(x)=x^2
2609 SET_CHILD_MAP(0)
2610 MERGE_APPROX_AND_PREC(mstruct)
2611 calculateRaise(nr_two, eo);
2612 return 1;
2613 } else if(mstruct.isFunction() && eo.protected_function != mstruct.function() && mstruct.function()->id() == FUNCTION_ID_SIGNUM && mstruct.size() == 2 && mstruct[0] == CHILD(0) && CHILD(0).representsScalar()) {
2614 // sgn(x)*abs(x)=x
2615 SET_CHILD_MAP(0)
2616 MERGE_APPROX_AND_PREC(mstruct)
2617 return 1;
2618 }
2619 } else if(o_function->id() == FUNCTION_ID_SIGNUM && SIZE == 2) {
2620 if(mstruct.isFunction() && mstruct.function()->id() == FUNCTION_ID_SIGNUM && mstruct.size() == 2 && mstruct[0] == CHILD(0) && CHILD(0).representsReal(true)) {
2621 if(mstruct[1].isOne() && CHILD(1).isOne()) {
2622 set(1, 1, 0, true);
2623 MERGE_APPROX_AND_PREC(mstruct)
2624 return 1;
2625 } else if(mstruct[1] == CHILD(1)) {
2626 // sgn(x)*sgn(x)=sgn(abs(x))
2627 CHILD(0).transformById(FUNCTION_ID_ABS);
2628 CHILD_UPDATED(0)
2629 MERGE_APPROX_AND_PREC(mstruct)
2630 return 1;
2631 }
2632 } else if(mstruct.isFunction() && eo.protected_function != mstruct.function() && mstruct.function()->id() == FUNCTION_ID_ABS && mstruct.size() == 1 && mstruct[0] == CHILD(0) && CHILD(0).representsScalar()) {
2633 // sgn(x)*abs(x)=x
2634 SET_CHILD_MAP(0)
2635 MERGE_APPROX_AND_PREC(mstruct)
2636 return 1;
2637 } else if(mstruct == CHILD(0) && CHILD(0).representsReal(true)) {
2638 // sgn(x)*x=abs(x)
2639 setFunctionId(FUNCTION_ID_ABS);
2640 ERASE(1)
2641 return 1;
2642 } else if(mstruct.isPower() && mstruct[1].representsOdd() && mstruct[0] == CHILD(0) && CHILD(0).representsReal(true)) {
2643 //sgn(x)*x^3=abs(x)^3
2644 mstruct[0].transformById(FUNCTION_ID_ABS);
2645 if(mparent) {
2646 mparent->swapChildren(index_this + 1, index_mstruct + 1);
2647 } else {
2648 set_nocopy(mstruct, true);
2649 }
2650 return 1;
2651 }
2652 } else if(o_function->id() == FUNCTION_ID_ROOT && THIS_VALID_ROOT) {
2653 if(CHILD(0) == mstruct && CHILD(0).representsReal(true) && CHILD(1).number().isOdd()) {
2654 // root(x, 3)*x=abs(x)^(1/3)*x
2655 CHILD(0).transformById(FUNCTION_ID_ABS);
2656 CHILD(1).number().recip();
2657 m_type = STRUCT_POWER;
2658 mstruct.transformById(FUNCTION_ID_ABS);
2659 mstruct.ref();
2660 multiply_nocopy(&mstruct);
2661 calculateMultiplyLast(eo);
2662 return 1;
2663 } else if(mstruct.isPower() && mstruct[1].representsOdd() && CHILD(0) == mstruct[0] && CHILD(0).representsReal(true) && CHILD(1).number().isOdd()) {
2664 // root(x, 3)*x^3=abs(x)^(1/3)*x^3
2665 CHILD(0).transformById(FUNCTION_ID_ABS);
2666 CHILD(1).number().recip();
2667 m_type = STRUCT_POWER;
2668 mstruct[0].transformById(FUNCTION_ID_ABS);
2669 mstruct.ref();
2670 multiply_nocopy(&mstruct);
2671 calculateMultiplyLast(eo);
2672 return 1;
2673 } else if(mstruct.isFunction() && mstruct.function()->id() == FUNCTION_ID_ROOT && VALID_ROOT(mstruct) && CHILD(0) == mstruct[0] && CHILD(0).representsReal(true) && CHILD(1).number().isOdd() && mstruct[1].number().isOdd()) {
2674 // root(x, y)*root(x, z)=abs(x)^(1/y)*abs(x)^(1/z)
2675 CHILD(0).transformById(FUNCTION_ID_ABS);
2676 CHILD(1).number().recip();
2677 m_type = STRUCT_POWER;
2678 mstruct[0].transformById(FUNCTION_ID_ABS);
2679 mstruct[1].number().recip();
2680 mstruct.setType(STRUCT_POWER);
2681 mstruct.ref();
2682 multiply_nocopy(&mstruct);
2683 calculateMultiplyLast(eo);
2684 return 1;
2685 } else if(mstruct.isPower() && mstruct[0].isFunction() && mstruct[0].function()->id() == FUNCTION_ID_ABS && mstruct[0].size() == 1 && mstruct[0][0].equals(CHILD(0)) && mstruct[1].isNumber() && mstruct[1].number().isRational() && mstruct[1].number().isFraction() && mstruct[0].number().denominator() == CHILD(1).number() && CHILD(0).representsReal(true) && mstruct[1].number().numerator() == CHILD(1).number() - 1) {
2686 // root(x, 3)*abs(x)^(2/3)=x
2687 SET_CHILD_MAP(0)
2688 return 1;
2689 }
2690 } else if((o_function->id() == FUNCTION_ID_LOG || o_function->id() == FUNCTION_ID_EXPINT) && SIZE == 1 && mstruct.isZero()) {
2691 // Ei(x)*0=0 if x is assumed non-zero
2692 if(CHILD(0).representsNonZero() || warn_about_assumed_not_value(CHILD(0), m_zero, eo)) {
2693 clear(true);
2694 MERGE_APPROX_AND_PREC(mstruct)
2695 return 3;
2696 }
2697 } else if(o_function->id() == FUNCTION_ID_LOGINT && SIZE == 1 && mstruct.isZero()) {
2698 // li(x)*0=0 if x is assumed not one
2699 if(representsNumber(true) || warn_about_assumed_not_value(CHILD(0), m_one, eo)) {
2700 clear(true);
2701 MERGE_APPROX_AND_PREC(mstruct)
2702 return 3;
2703 }
2704 } else if(o_function->id() == FUNCTION_ID_TAN && SIZE == 1 && mstruct.isZero()) {
2705 setFunctionId(FUNCTION_ID_COS);
2706 if(warn_about_assumed_not_value(*this, m_zero, eo)) {
2707 // 0*tan(x)=0 if cos(x) is assume non-zero
2708 clear(true);
2709 MERGE_APPROX_AND_PREC(mstruct)
2710 return 3;
2711 }
2712 setFunctionId(FUNCTION_ID_TAN);
2713 } else if(eo.transform_trigonometric_functions && o_function->id() == FUNCTION_ID_SINC && SIZE == 1 && CHILD(0) == mstruct) {
2714 // sinc(x)*x=sin(x)
2715 CHILD(0).calculateMultiply(CALCULATOR->getRadUnit(), eo);
2716 CHILD_UPDATED(0)
2717 setFunctionId(FUNCTION_ID_SIN);
2718 if(eo.calculate_functions) calculateFunctions(eo, false);
2719 MERGE_APPROX_AND_PREC(mstruct)
2720 return 1;
2721 } else if(eo.transform_trigonometric_functions && mstruct.isFunction() && mstruct.size() == 1 && eo.protected_function != mstruct.function()) {
2722 if(o_function->id() == FUNCTION_ID_TAN && SIZE == 1) {
2723 if(mstruct.function()->id() == FUNCTION_ID_COS && mstruct[0] == CHILD(0)) {
2724 // tan(x)*cos(x)=sin(x)
2725 setFunctionId(FUNCTION_ID_SIN);
2726 MERGE_APPROX_AND_PREC(mstruct)
2727 return 1;
2728 }
2729 } else if(o_function->id() == FUNCTION_ID_COS && SIZE == 1) {
2730 if(mstruct.function()->id() == FUNCTION_ID_TAN && mstruct[0] == CHILD(0)) {
2731 // tan(x)*cos(x)=sin(x)
2732 setFunctionId(FUNCTION_ID_SIN);
2733 MERGE_APPROX_AND_PREC(mstruct)
2734 return 1;
2735 } else if(mstruct.function()->id() == FUNCTION_ID_SIN && mstruct[0] == CHILD(0)) {
2736 // cos(x)*sin(x)=sin(2x)/2
2737 setFunctionId(FUNCTION_ID_SIN);
2738 CHILD(0).calculateMultiply(nr_two, eo);
2739 CHILD_UPDATED(0)
2740 calculateDivide(nr_two, eo);
2741 MERGE_APPROX_AND_PREC(mstruct)
2742 return 1;
2743 }
2744 } else if(o_function->id() == FUNCTION_ID_SIN && SIZE == 1) {
2745 if(mstruct.function()->id() == FUNCTION_ID_COS && mstruct[0] == CHILD(0)) {
2746 // cos(x)*sin(x)=sin(2x)/2
2747 setFunctionId(FUNCTION_ID_SIN);
2748 CHILD(0).calculateMultiply(nr_two, eo);
2749 CHILD_UPDATED(0)
2750 calculateDivide(nr_two, eo);
2751 MERGE_APPROX_AND_PREC(mstruct)
2752 return 1;
2753 }
2754 } else if(o_function->id() == FUNCTION_ID_TANH && SIZE == 1) {
2755 if(mstruct.function()->id() == FUNCTION_ID_COSH && mstruct[0] == CHILD(0)) {
2756 // tanh(x)*cosh(x)=sinh(x)
2757 setFunctionId(FUNCTION_ID_SINH);
2758 MERGE_APPROX_AND_PREC(mstruct)
2759 return 1;
2760 }
2761 } else if(o_function->id() == FUNCTION_ID_SINH && SIZE == 1) {
2762 if(mstruct.function()->id() == FUNCTION_ID_COSH && mstruct[0] == CHILD(0)) {
2763 // cosh(x)*sinh(x)=sinh(2x)/2
2764 setFunctionId(FUNCTION_ID_SINH);
2765 CHILD(0).calculateMultiply(nr_two, eo);
2766 CHILD_UPDATED(0)
2767 calculateDivide(nr_two, eo);
2768 MERGE_APPROX_AND_PREC(mstruct)
2769 return 1;
2770 }
2771 } else if(o_function->id() == FUNCTION_ID_COSH && SIZE == 1) {
2772 if(mstruct.function()->id() == FUNCTION_ID_TANH && mstruct[0] == CHILD(0)) {
2773 // tanh(x)*cosh(x)=sinh(x)
2774 setFunctionId(FUNCTION_ID_SINH);
2775 MERGE_APPROX_AND_PREC(mstruct)
2776 return 1;
2777 } else if(mstruct.function()->id() == FUNCTION_ID_SINH && mstruct[0] == CHILD(0)) {
2778 // cosh(x)*sinh(x)=sinh(2x)/2
2779 setFunctionId(FUNCTION_ID_SINH);
2780 CHILD(0).calculateMultiply(nr_two, eo);
2781 CHILD_UPDATED(0)
2782 calculateDivide(nr_two, eo);
2783 MERGE_APPROX_AND_PREC(mstruct)
2784 return 1;
2785 }
2786 }
2787 }
2788 }
2789 if(o_function->id() == FUNCTION_ID_STRIP_UNITS && SIZE == 1) {
2790 if(mstruct.isFunction() && mstruct.function()->id() == FUNCTION_ID_STRIP_UNITS && mstruct.size() == 1) {
2791 // nounit(x)*nounit(y)=nounit(x*y)
2792 mstruct[0].ref();
2793 CHILD(0).multiply_nocopy(&mstruct[0]);
2794 return 1;
2795 } else if(mstruct.isVariable() && mstruct.variable()->isKnown() && CHILD(0).contains(mstruct, false) > 0) {
2796 // nounit(v)*v=nounit(v)*nounit(v)*(units in v)
2797 // try extracting units from variable
2798 if(separate_unit_vars(mstruct, eo, false)) {
2799 mstruct.ref();
2800 multiply_nocopy(&mstruct);
2801 calculateMultiplyLast(eo);
2802 return 1;
2803 }
2804 } else if(mstruct.isPower() && mstruct[0].isVariable() && mstruct[0].variable()->isKnown() && CHILD(0).contains(mstruct[0], false) > 0) {
2805 // nounit(v)*v^a=nounit(v)*(nounit(v)*(units in v))^a
2806 // try extracting units from variable
2807 if(separate_unit_vars(mstruct[0], eo, false)) {
2808 mstruct.calculateRaiseExponent(eo);
2809 mstruct.ref();
2810 multiply_nocopy(&mstruct);
2811 calculateMultiplyLast(eo);
2812 return 1;
2813 }
2814 }
2815 }
2816 }
2817 default: {
2818 switch(mstruct.type()) {
2819 case STRUCT_VECTOR: {}
2820 case STRUCT_ADDITION: {}
2821 case STRUCT_MULTIPLICATION: {}
2822 case STRUCT_POWER: {
2823 // try again with reversed order
2824 return 0;
2825 }
2826 case STRUCT_COMPARISON: {
2827 if(isComparison()) {
2828 // use logical and for multiplication of comparisons (logical and equals multiplication)
2829 mstruct.ref();
2830 transform_nocopy(STRUCT_LOGICAL_AND, &mstruct);
2831 return 1;
2832 }
2833 }
2834 default: {
2835 if(mstruct.isFunction() && mstruct.function()->id() == FUNCTION_ID_STRIP_UNITS && mstruct.size() == 1) {
2836 if(m_type == STRUCT_VARIABLE && o_variable->isKnown() && mstruct[0].contains(*this, false) > 0) {
2837 // v*nounit(v)=nounit(v)*nounit(v)*(units in v)
2838 // try extracting units from variable
2839 if(separate_unit_vars(*this, eo, false)) {
2840 mstruct.ref();
2841 multiply_nocopy(&mstruct);
2842 calculateMultiplyLast(eo);
2843 return 1;
2844 }
2845 }
2846 }
2847 // x*0=0 (keep units and check if not matrix and not undefined)
2848 if(mstruct.isZero() && (!eo.keep_zero_units || containsType(STRUCT_UNIT, false, true, true) <= 0 || (isUnit() && unit() == CALCULATOR->getRadUnit()) || (isFunction() && representsNumber(false))) && !representsUndefined(true, true, !eo.assume_denominators_nonzero) && representsNonMatrix()) {
2849 clear(true);
2850 MERGE_APPROX_AND_PREC(mstruct)
2851 return 3;
2852 }
2853 // 0*x=0 (keep units and check if not matrix and not undefined)
2854 if(isZero() && !mstruct.representsUndefined(true, true, !eo.assume_denominators_nonzero) && (!eo.keep_zero_units || mstruct.containsType(STRUCT_UNIT, false, true, true) <= 0 || (mstruct.isUnit() && mstruct.unit() == CALCULATOR->getRadUnit())) && mstruct.representsNonMatrix()) {
2855 MERGE_APPROX_AND_PREC(mstruct)
2856 return 2;
2857 }
2858 if(equals(mstruct)) {
2859 // x*x=x^2
2860 if(mstruct.isUnit() && mstruct.prefix()) o_prefix = mstruct.prefix();
2861 raise_nocopy(new MathStructure(2, 1, 0));
2862 MERGE_APPROX_AND_PREC(mstruct)
2863 calculateRaiseExponent(eo, mparent, index_this);
2864 return 1;
2865 }
2866 break;
2867 }
2868 }
2869 break;
2870 }
2871 }
2872 return -1;
2873 }
2874
test_if_numerator_not_too_large(Number & vb,Number & ve)2875 bool test_if_numerator_not_too_large(Number &vb, Number &ve) {
2876 if(!vb.isRational()) return false;
2877 if(!mpz_fits_slong_p(mpq_numref(ve.internalRational()))) return false;
2878 long int exp = labs(mpz_get_si(mpq_numref(ve.internalRational())));
2879 if(vb.isRational()) {
2880 if((long long int) exp * mpz_sizeinbase(mpq_numref(vb.internalRational()), 10) <= 1000000LL && (long long int) exp * mpz_sizeinbase(mpq_denref(vb.internalRational()), 10) <= 1000000LL) return true;
2881 }
2882 return false;
2883 }
2884
is_negation(const MathStructure & m1,const MathStructure & m2)2885 bool is_negation(const MathStructure &m1, const MathStructure &m2) {
2886 if(m1.isAddition() && m2.isAddition() && m1.size() == m2.size()) {
2887 for(size_t i = 0; i < m1.size(); i++) {
2888 if(!is_negation(m1[i], m2[i])) return false;
2889 }
2890 return true;
2891 }
2892 if(m1.isNumber() && m2.isNumber()) {
2893 return m1.number() == -m2.number();
2894 }
2895 if(m1.isMultiplication() && m1.size() > 1) {
2896 if(m1[0].isNumber()) {
2897 if(m1[0].number().isMinusOne()) {
2898 if(m1.size() == 2) return m1[1] == m2;
2899 if(m2.isMultiplication() && m2.size() == m1.size() - 1) {
2900 for(size_t i = 1; i < m1.size(); i++) {
2901 if(!m1[i].equals(m2[i - 1], true, true)) return false;
2902 }
2903 return true;
2904 }
2905 return false;
2906 } else {
2907 if(m2.isMultiplication() && m2.size() == m1.size() && m2[0].isNumber()) {
2908 for(size_t i = 1; i < m1.size(); i++) {
2909 if(!m1[i].equals(m2[i], true, true)) return false;
2910 }
2911 return m1[0].number().equals(-m2[0].number(), true, true);
2912 }
2913 return false;
2914 }
2915 }
2916 }
2917 if(m2.isMultiplication() && m2.size() > 1) {
2918 if(m2[0].isNumber()) {
2919 if(m2[0].number().isMinusOne()) {
2920 if(m2.size() == 2) return m2[1] == m1;
2921 if(m1.isMultiplication() && m1.size() == m2.size() - 1) {
2922 for(size_t i = 1; i < m2.size(); i++) {
2923 if(!m2[i].equals(m1[i - 1], true, true)) return false;
2924 }
2925 return true;
2926 }
2927 return false;
2928 }
2929 }
2930 }
2931 return false;
2932 }
2933
merge_power(MathStructure & mstruct,const EvaluationOptions & eo,MathStructure * mparent,size_t index_this,size_t index_mstruct,bool)2934 int MathStructure::merge_power(MathStructure &mstruct, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this, size_t index_mstruct, bool) {
2935 // test if base and exponent can be merged
2936 if(mstruct.type() == STRUCT_NUMBER && m_type == STRUCT_NUMBER) {
2937 // base and exponent are numbers try Number::raise()
2938 Number nr(o_number);
2939 if(nr.raise(mstruct.number(), eo.approximation < APPROXIMATION_APPROXIMATE) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || mstruct.number().isApproximate()) && (eo.allow_complex || !nr.isComplex() || o_number.isComplex() || mstruct.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || o_number.includesInfinity() || mstruct.number().includesInfinity())) {
2940 // Exponentiation succeeded without inappropriate change in approximation status
2941 if(o_number == nr) {
2942 o_number = nr;
2943 numberUpdated();
2944 return 2;
2945 }
2946 o_number = nr;
2947 numberUpdated();
2948 return 1;
2949 }
2950 if(!o_number.isMinusOne() && !o_number.isOne() && mstruct.number().isRational() && !mstruct.isInteger()) {
2951 if(o_number.isRational() && !o_number.isZero() && mstruct.number().isFraction()) {
2952 if(mstruct.number().isNegative() && cmp_num_abs_2_to_den(mstruct.number()) >= 0) {
2953 // a^(-b)=a^(-b+1)/a
2954 Number nmul(o_number);
2955 nmul.recip();
2956 mstruct.number()++;
2957 calculateRaise(mstruct, eo);
2958 calculateMultiply(nmul, eo);
2959 return 1;
2960 } else if(mstruct.number().isPositive() && cmp_num_abs_2_to_den(mstruct.number()) > 0) {
2961 // a^b=a^(b-1)*a
2962 Number nmul(o_number);
2963 mstruct.number()--;
2964 calculateRaise(mstruct, eo);
2965 calculateMultiply(nmul, eo);
2966 return 1;
2967 }
2968 }
2969 if(o_number.isNegative()) {
2970 // (-a)^b=(-1)^b*a^b
2971 MathStructure mtest(*this);
2972 if(mtest.number().negate() && mtest.calculateRaise(mstruct, eo)) {
2973 set(mtest);
2974 MathStructure *mmul = new MathStructure(-1, 1, 0);
2975 mmul->calculateRaise(mstruct, eo);
2976 multiply_nocopy(mmul);
2977 calculateMultiplyLast(eo);
2978 return 1;
2979 }
2980 } else {
2981 Number exp_num(mstruct.number().numerator());
2982 if(!exp_num.isOne() && !exp_num.isMinusOne() && o_number.isPositive() && test_if_numerator_not_too_large(o_number, exp_num)) {
2983 // a^(n/d)=(a^n)^(1/d)
2984 nr = o_number;
2985 if(nr.raise(exp_num, eo.approximation < APPROXIMATION_APPROXIMATE) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || mstruct.number().isApproximate()) && (eo.allow_complex || !nr.isComplex() || o_number.isComplex() || mstruct.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || o_number.includesInfinity() || mstruct.number().includesInfinity())) {
2986 o_number = nr;
2987 numberUpdated();
2988 nr.set(mstruct.number().denominator());
2989 nr.recip();
2990 calculateRaise(nr, eo, mparent, index_this);
2991 return 1;
2992 }
2993 }
2994 if(o_number.isPositive()) {
2995 Number nr_root(mstruct.number().denominator());
2996 if(eo.split_squares && o_number.isInteger() && o_number.integerLength() < 100000L && nr_root.isLessThanOrEqualTo(LARGEST_RAISED_PRIME_EXPONENT)) {
2997 // a^(1/d)=b^(1/d)*(a/b)^(1/d)
2998 // search list of primes raised by the exponent denominator for value which can divide the base without remainder
2999 int root = nr_root.intValue();
3000 nr.set(1, 1, 0);
3001 bool b = true, overflow;
3002 long int val;
3003 while(b) {
3004 if(CALCULATOR->aborted()) break;
3005 b = false;
3006 overflow = false;
3007 val = o_number.lintValue(&overflow);
3008 if(overflow) {
3009 mpz_srcptr cval = mpq_numref(o_number.internalRational());
3010 for(size_t i = 0; root == 2 ? (i < NR_OF_SQUARE_PRIMES) : (RAISED_PRIMES[root - 3][i] != 0); i++) {
3011 if(CALCULATOR->aborted()) break;
3012 if(mpz_divisible_ui_p(cval, (unsigned long int) (root == 2 ? SQUARE_PRIMES[i] : RAISED_PRIMES[root - 3][i]))) {
3013 nr *= PRIMES[i];
3014 o_number /= (root == 2 ? SQUARE_PRIMES[i] : RAISED_PRIMES[root - 3][i]);
3015 b = true;
3016 break;
3017 }
3018 }
3019 } else {
3020 for(size_t i = 0; root == 2 ? (i < NR_OF_SQUARE_PRIMES) : (RAISED_PRIMES[root - 3][i] != 0); i++) {
3021 if(CALCULATOR->aborted()) break;
3022 if((root == 2 ? SQUARE_PRIMES[i] : RAISED_PRIMES[root - 3][i]) > val) {
3023 break;
3024 } else if(val % (root == 2 ? SQUARE_PRIMES[i] : RAISED_PRIMES[root - 3][i]) == 0) {
3025 nr *= PRIMES[i];
3026 o_number /= (root == 2 ? SQUARE_PRIMES[i] : RAISED_PRIMES[root - 3][i]);
3027 b = true;
3028 break;
3029 }
3030 }
3031 }
3032 }
3033 if(!nr.isOne()) {
3034 transform(STRUCT_MULTIPLICATION);
3035 CHILD(0).calculateRaise(mstruct, eo, this, 0);
3036 PREPEND(nr);
3037 if(!mstruct.number().numeratorIsOne()) {
3038 CHILD(0).calculateRaise(mstruct.number().numerator(), eo, this, 0);
3039 }
3040 calculateMultiplyIndex(0, eo, true, mparent, index_this);
3041 return 1;
3042 }
3043 }
3044 if(eo.split_squares && nr_root != 2) {
3045 // partial roots, e.g. 9^(1/4)=3^(1/2)
3046 // if denominator is even try square root
3047 if(nr_root.isEven()) {
3048 Number nr(o_number);
3049 if(nr.sqrt() && !nr.isApproximate()) {
3050 o_number = nr;
3051 mstruct.number().multiply(2);
3052 mstruct.ref();
3053 raise_nocopy(&mstruct);
3054 calculateRaiseExponent(eo, mparent, index_this);
3055 return 1;
3056 }
3057 }
3058 // test if denominator is divisible with prime number (each from PRIMES array) and try calculating root
3059 for(size_t i = 1; i < NR_OF_PRIMES; i++) {
3060 if(nr_root.isLessThanOrEqualTo(PRIMES[i])) break;
3061 if(nr_root.isIntegerDivisible(PRIMES[i])) {
3062 Number nr(o_number);
3063 if(nr.root(Number(PRIMES[i], 1)) && !nr.isApproximate()) {
3064 o_number = nr;
3065 mstruct.number().multiply(PRIMES[i]);
3066 mstruct.ref();
3067 raise_nocopy(&mstruct);
3068 calculateRaiseExponent(eo, mparent, index_this);
3069 return 1;
3070 }
3071 }
3072 }
3073 }
3074 }
3075 }
3076 }
3077 if(o_number.isMinusOne() && mstruct.number().isRational()) {
3078 if(mstruct.number().isInteger()) {
3079 // (-1)^n equals 1 if n is even, -1 if n is odd (is normally handled above)
3080 if(mstruct.number().isEven()) set(m_one, true);
3081 else set(m_minus_one, true);
3082 MERGE_APPROX_AND_PREC(mstruct)
3083 return 1;
3084 } else {
3085 Number nr_floor(mstruct.number());
3086 nr_floor.floor();
3087 if(mstruct.number().denominatorIsTwo()) {
3088 // (-1)^(n/2) equals i if floor(n/2) is even and -i if floor(n/2) is odd
3089 if(nr_floor.isEven()) set(nr_one_i, true);
3090 else set(nr_minus_i, true);
3091 MERGE_APPROX_AND_PREC(mstruct)
3092 return 1;
3093 } else {
3094 mstruct.number() -= nr_floor;
3095 mstruct.numberUpdated();
3096 if(mstruct.number().denominator() == 3) {
3097 // (-1)^(n/3) equals (1+sqrt(3)*i)/2; negate if floor(n/3) is odd
3098 set(3, 1, 0, true);
3099 calculateRaise(nr_half, eo);
3100 if(nr_floor.isEven()) calculateMultiply(nr_one_i, eo);
3101 else calculateMultiply(nr_minus_i, eo);
3102 calculateMultiply(nr_half, eo);
3103 if(nr_floor.isEven() == mstruct.number().numeratorIsOne()) calculateAdd(nr_half, eo);
3104 else calculateAdd(nr_minus_half, eo);
3105 MERGE_APPROX_AND_PREC(mstruct)
3106 return 1;
3107 } else if(mstruct.number().denominator() == 4) {
3108 // (-1)^(n/4) equals (1+i)*1/sqrt(2) if floor(n/4) is even and (-1-i)*1/sqrt(2) if floor(n/4) is odd
3109 if(nr_floor.isEven() == mstruct.number().numeratorIsOne()) set(1, 1, 0, true);
3110 else set(-1, 1, 0, true);
3111 if(nr_floor.isEven()) calculateAdd(nr_one_i, eo);
3112 else calculateAdd(nr_minus_i, eo);
3113 multiply(nr_two);
3114 LAST.calculateRaise(nr_minus_half, eo);
3115 calculateMultiplyLast(eo);
3116 MERGE_APPROX_AND_PREC(mstruct)
3117 return 1;
3118 } else if(!nr_floor.isZero()) {
3119 // (-1)^(n/d)=(-1)^(n/d-floor(n/d)); negate if floor(n/d) is odd
3120 // e.g. (-1)^(7/5)=-(-1)^(2/5)
3121 mstruct.ref();
3122 raise_nocopy(&mstruct);
3123 calculateRaiseExponent(eo);
3124 if(nr_floor.isOdd()) calculateNegate(eo);
3125 return 1;
3126 }
3127 }
3128 }
3129 }
3130 if(o_number.isRational() && !o_number.isInteger() && !o_number.numeratorIsOne() && mstruct.number().isRational()) {
3131 // (n/d)^a=n^a*1/d^a
3132 Number num(o_number.numerator());
3133 Number den(o_number.denominator());
3134 if(den.integerLength() < 100000L && num.integerLength() < 100000L) {
3135 set(num, true);
3136 calculateRaise(mstruct, eo);
3137 multiply(den);
3138 LAST.calculateRaise(mstruct, eo);
3139 LAST.calculateInverse(eo);
3140 calculateMultiplyLast(eo);
3141 return 1;
3142 }
3143 }
3144 // If base numerator is larger than denominator, invert base and negate exponent
3145 if(o_number.isRational() && !o_number.isInteger() && !o_number.isZero() && ((o_number.isNegative() && o_number.isGreaterThan(nr_minus_one) && mstruct.number().isInteger()) || (o_number.isPositive() && o_number.isLessThan(nr_one)))) {
3146 mstruct.number().negate();
3147 o_number.recip();
3148 return 0;
3149 }
3150 return -1;
3151 }
3152
3153 if(mstruct.isOne()) {
3154 // x^1=x
3155 MERGE_APPROX_AND_PREC(mstruct)
3156 return 2;
3157 } else if(isOne() && mstruct.representsNumber()) {
3158 // 1^x=1
3159 MERGE_APPROX_AND_PREC(mstruct)
3160 return 1;
3161 }
3162 if(m_type == STRUCT_NUMBER && o_number.isInfinite(false)) {
3163 if(mstruct.representsNegative(false)) {
3164 // infinity^(-a)=0
3165 o_number.clear();
3166 MERGE_APPROX_AND_PREC(mstruct)
3167 return 1;
3168 } else if(mstruct.representsPositive(false)) {
3169 if(o_number.isMinusInfinity()) {
3170 if(mstruct.representsEven(false)) {
3171 // (-infinity)^a=infinity if a is even
3172 o_number.setPlusInfinity();
3173 MERGE_APPROX_AND_PREC(mstruct)
3174 return 1;
3175 } else if(mstruct.representsOdd(false)) {
3176 // (-infinity)^a=-infinity if a is odd
3177 MERGE_APPROX_AND_PREC(mstruct)
3178 return 1;
3179 }
3180 } else if(o_number.isPlusInfinity()) {
3181 // infinity^a=infinity
3182 MERGE_APPROX_AND_PREC(mstruct)
3183 return 1;
3184 }
3185 }
3186 MathStructure mtest(mstruct);
3187 CALCULATOR->beginTemporaryEnableIntervalArithmetic();
3188 if(CALCULATOR->usesIntervalArithmetic()) {
3189 CALCULATOR->beginTemporaryStopMessages();
3190 EvaluationOptions eo2 = eo;
3191 eo2.approximation = APPROXIMATION_APPROXIMATE;
3192 if(eo2.interval_calculation == INTERVAL_CALCULATION_NONE) eo2.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC;
3193 mtest.calculateFunctions(eo2);
3194 mtest.calculatesub(eo2, eo2);
3195 CALCULATOR->endTemporaryStopMessages();
3196 }
3197 CALCULATOR->endTemporaryEnableIntervalArithmetic();
3198 if(mtest.representsNegative(false)) {
3199 // infinity^(-a)=0
3200 o_number.clear();
3201 MERGE_APPROX_AND_PREC(mstruct)
3202 return 1;
3203 } else if(mtest.representsNonZero(false) && mtest.representsPositive(false)) {
3204 if(o_number.isMinusInfinity()) {
3205 if(mstruct.representsEven(false)) {
3206 // (-infinity)^a=infinity if a is even
3207 o_number.setPlusInfinity();
3208 MERGE_APPROX_AND_PREC(mstruct)
3209 return 1;
3210 } else if(mstruct.representsOdd(false)) {
3211 // (-infinity)^a=-infinity if a is odd
3212 MERGE_APPROX_AND_PREC(mstruct)
3213 return 1;
3214 }
3215 } else if(o_number.isPlusInfinity()) {
3216 // infinity^a=infinity
3217 MERGE_APPROX_AND_PREC(mstruct)
3218 return 1;
3219 }
3220 }
3221 } else if(mstruct.isNumber() && mstruct.number().isInfinite(false)) {
3222 // test calculation of base when exponent is infinite
3223 MathStructure mtest(*this);
3224 CALCULATOR->beginTemporaryEnableIntervalArithmetic();
3225 if(CALCULATOR->usesIntervalArithmetic()) {
3226 CALCULATOR->beginTemporaryStopMessages();
3227 EvaluationOptions eo2 = eo;
3228 eo2.approximation = APPROXIMATION_APPROXIMATE;
3229 if(eo2.interval_calculation == INTERVAL_CALCULATION_NONE) eo2.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC;
3230 mtest.calculateFunctions(eo2);
3231 mtest.calculatesub(eo2, eo2);
3232 CALCULATOR->endTemporaryStopMessages();
3233 }
3234 CALCULATOR->endTemporaryEnableIntervalArithmetic();
3235 if(mtest.isNumber()) {
3236 if(mtest.merge_power(mstruct, eo) > 0 && mtest.isNumber()) {
3237 if(mtest.number().isPlusInfinity()) {
3238 set(nr_plus_inf, true);
3239 MERGE_APPROX_AND_PREC(mstruct)
3240 return 1;
3241 } else if(mtest.number().isMinusInfinity()) {
3242 set(nr_minus_inf, true);
3243 MERGE_APPROX_AND_PREC(mstruct)
3244 return 1;
3245 } else if(mtest.number().isZero()) {
3246 clear(true);
3247 MERGE_APPROX_AND_PREC(mstruct)
3248 return 1;
3249 }
3250 }
3251 }
3252 }
3253
3254 if(representsUndefined() || mstruct.representsUndefined()) return -1;
3255 if(isZero() && mstruct.representsPositive()) {
3256 // 0^a=0 if a is positive
3257 return 1;
3258 }
3259 if(mstruct.isZero() && !representsUndefined(true, true)) {
3260 // x^0=1
3261 set(m_one);
3262 MERGE_APPROX_AND_PREC(mstruct)
3263 return 1;
3264 }
3265
3266 switch(m_type) {
3267 case STRUCT_VECTOR: {
3268 if(mstruct.isNumber() && mstruct.number().isInteger()) {
3269 if(isMatrix()) {
3270 // matrix multiplication: m^n=m*m*m...
3271 // requires equal number of columns and rows (columns of 1st matrix must be equal to rows in 2nd matrix)
3272 if(matrixIsSquare()) {
3273 Number nr(mstruct.number());
3274 // handle matrix inversion after multiplication
3275 bool b_neg = false;
3276 if(nr.isNegative()) {
3277 nr.setNegative(false);
3278 b_neg = true;
3279 }
3280 if(!nr.isOne()) {
3281 MathStructure msave(*this);
3282 nr--;
3283 while(nr.isPositive()) {
3284 if(CALCULATOR->aborted()) {
3285 set(msave);
3286 return -1;
3287 }
3288 calculateMultiply(msave, eo);
3289 nr--;
3290 }
3291 }
3292 if(b_neg) {
3293 // exponent is negative: invert matrix
3294 if(!invertMatrix(eo)) {
3295 if(mstruct.number().isMinusOne()) return -1;
3296 raise(nr_minus_one);
3297 }
3298 }
3299 MERGE_APPROX_AND_PREC(mstruct)
3300 return 1;
3301 }
3302 return -1;
3303 } else {
3304 // vector multiplication: do v^n=v^(n-1)*v
3305 if(mstruct.number().isMinusOne()) {
3306 return -1;
3307 }
3308 Number nr(mstruct.number());
3309 if(nr.isNegative()) {
3310 nr++;
3311 } else {
3312 nr--;
3313 }
3314 MathStructure msave(*this);
3315 calculateMultiply(msave, eo);
3316 calculateRaise(nr, eo);
3317 MERGE_APPROX_AND_PREC(mstruct)
3318 return 1;
3319 }
3320
3321 }
3322 goto default_power_merge;
3323 }
3324 case STRUCT_ADDITION: {
3325 if(mstruct.isNumber() && mstruct.number().isInteger() && containsType(STRUCT_DATETIME, false, true, false) <= 0) {
3326 if(eo.reduce_divisions && mstruct.number().isMinusOne()) {
3327 // 1/(a1+a2+...)
3328 int bnum = -1, bden = -1;
3329 // count difference between number of negative and positive terms
3330 int inegs = 0;
3331 bool b_break = false;
3332 for(size_t i = 0; i < SIZE && !b_break; i++) {
3333 switch(CHILD(i).type()) {
3334 case STRUCT_NUMBER: {
3335 if(!CHILD(i).number().isRational() || CHILD(i).number().numeratorIsGreaterThan(1000000L) || CHILD(i).number().numeratorIsLessThan(-1000000L) || CHILD(i).number().denominatorIsGreaterThan(1000L)) {
3336 bnum = 0; bden = 0; inegs = 0; b_break = true;
3337 }
3338 if(bden != 0 && !CHILD(i).number().isInteger()) bden = 1;
3339 if(bnum != 0 && !CHILD(i).isZero()) {
3340 if(CHILD(i).number().numeratorIsOne() || CHILD(i).number().numeratorIsMinusOne()) bnum = 0;
3341 else bnum = 1;
3342 }
3343 if(CHILD(i).number().hasNegativeSign()) {
3344 //negative term
3345 inegs++;
3346 // negative first term counts double
3347 // (for predictable result when number of negative and positive terms are equal)
3348 if(i == 0) inegs++;
3349 } else if(!CHILD(i).number().isZero()) {
3350 // positive term
3351 inegs--;
3352 }
3353 break;
3354 }
3355 case STRUCT_MULTIPLICATION: {
3356 if(CHILD(i).size() > 0 && CHILD(i)[0].isNumber()) {
3357 if(!CHILD(i)[0].number().isRational() || CHILD(i)[0].number().numeratorIsGreaterThan(1000000L) || CHILD(i)[0].number().numeratorIsLessThan(-1000000L) || CHILD(i)[0].number().denominatorIsGreaterThan(1000L)) {
3358 bnum = 0; bden = 0; inegs = 0; b_break = true;
3359 }
3360 if(bden != 0 && !CHILD(i)[0].number().isInteger()) bden = 1;
3361 if(bnum != 0 && !CHILD(i)[0].isZero()) {
3362 if(CHILD(i)[0].number().numeratorIsOne() || CHILD(i)[0].number().numeratorIsMinusOne()) bnum = 0;
3363 else bnum = 1;
3364 }
3365 if(CHILD(i)[0].number().hasNegativeSign()) {
3366 //negative term
3367 inegs++;
3368 // negative first term counts double
3369 if(i == 0) inegs++;
3370 } else if(!CHILD(i)[0].number().isZero()) {
3371 // positive term
3372 inegs--;
3373 }
3374 break;
3375 }
3376 }
3377 default: {
3378 bnum = 0;
3379 inegs--;
3380 break;
3381 }
3382 }
3383 }
3384 if(bden < 0) bden = 0;
3385 if(bnum < 0) bnum = 0;
3386 if(bnum || bden) {
3387 // denominator only contains rational multipliers (non-numerical values excluded)
3388 // if bnum is true, denonimator contains multiplier with numerator > 1:
3389 // determine the greater common divisor of multiplier numerators
3390 // if bden is true, denominator contains non-integer multipliers:
3391 // determine least common multiplier of multiplier denominators
3392 Number nr_num, nr_den(1, 1, 0);
3393 for(size_t i = 0; i < SIZE && !nr_den.isZero(); i++) {
3394 switch(CHILD(i).type()) {
3395 case STRUCT_NUMBER: {
3396 if(CHILD(i).number().isInteger()) {
3397 if(bnum && !nr_num.isOne() && !CHILD(i).number().isZero()) {
3398 if(nr_num.isZero()) nr_num = CHILD(i).number();
3399 else nr_num.gcd(CHILD(i).number());
3400 }
3401 } else {
3402 if(bnum && !nr_num.isOne() && !CHILD(i).number().isZero()) {
3403 if(nr_num.isZero()) nr_num = CHILD(i).number().numerator();
3404 else nr_num.gcd(CHILD(i).number().numerator());
3405 }
3406 if(bden) {
3407 nr_den.lcm(CHILD(i).number().denominator());
3408 if(nr_den.isGreaterThan(1000000L)) nr_den.clear();
3409 }
3410 }
3411 break;
3412 }
3413 case STRUCT_MULTIPLICATION: {
3414 if(CHILD(i).size() > 0 && CHILD(i)[0].isNumber()) {
3415 if(CHILD(i)[0].number().isInteger()) {
3416 if(bnum && !nr_num.isOne() && !CHILD(i)[0].number().isZero()) {
3417 if(nr_num.isZero()) nr_num = CHILD(i)[0].number();
3418 else nr_num.gcd(CHILD(i)[0].number());
3419 }
3420 } else {
3421 if(bnum && !nr_num.isOne() && !CHILD(i)[0].number().isZero()) {
3422 if(nr_num.isZero()) nr_num = CHILD(i)[0].number().numerator();
3423 else nr_num.gcd(CHILD(i)[0].number().numerator());
3424 }
3425 if(bden) {
3426 nr_den.lcm(CHILD(i)[0].number().denominator());
3427 if(nr_den.isGreaterThan(1000000L)) nr_den.clear();
3428 }
3429 }
3430 break;
3431 }
3432 }
3433 default: {
3434 break;
3435 }
3436 }
3437 }
3438 if(!nr_den.isZero() && (!nr_den.isOne() || !nr_num.isOne())) {
3439 Number nr(nr_den);
3440 nr.divide(nr_num);
3441 nr.setNegative(inegs > 0);
3442 // multiply each term by lcm/gcd
3443 // if the number of negative terms is greater than the number of positive terms, negate all terms
3444 for(size_t i = 0; i < SIZE; i++) {
3445 switch(CHILD(i).type()) {
3446 case STRUCT_NUMBER: {
3447 CHILD(i).number() *= nr;
3448 break;
3449 }
3450 case STRUCT_MULTIPLICATION: {
3451 if(CHILD(i).size() > 0 && CHILD(i)[0].isNumber()) {
3452 CHILD(i)[0].number() *= nr;
3453 CHILD(i).calculateMultiplyIndex(0, eo, true, this, i);
3454 break;
3455 }
3456 }
3457 default: {
3458 CHILD(i).calculateMultiply(nr, eo);
3459 }
3460 }
3461 }
3462 calculatesub(eo, eo, false);
3463 mstruct.ref();
3464 raise_nocopy(&mstruct);
3465 calculateRaiseExponent(eo);
3466 calculateMultiply(nr, eo, mparent, index_this);
3467 return 1;
3468 }
3469 }
3470 if(inegs > 0) {
3471 // if the number of negative terms is greater than the number of positive terms: 1/(a1+a2+...)=-1/(-a1-a2-...)
3472 // this makes it easier the handle expressions such as 1/(a1-a2-a3+a4)+1/(-a1+a2+a3-a4) (=0)
3473 for(size_t i = 0; i < SIZE; i++) {
3474 switch(CHILD(i).type()) {
3475 case STRUCT_NUMBER: {CHILD(i).number().negate(); break;}
3476 case STRUCT_MULTIPLICATION: {
3477 if(CHILD(i).size() > 0 && CHILD(i)[0].isNumber()) {
3478 CHILD(i)[0].number().negate();
3479 CHILD(i).calculateMultiplyIndex(0, eo, true, this, i);
3480 break;
3481 }
3482 }
3483 default: {
3484 CHILD(i).calculateNegate(eo);
3485 }
3486 }
3487 }
3488 mstruct.ref();
3489 raise_nocopy(&mstruct);
3490 negate();
3491 return 1;
3492 }
3493 } else if(eo.expand != 0 && !mstruct.number().isZero() && (eo.expand > -2 || !containsInterval())) {
3494 // (a1+a2+a3...)^b
3495 bool b = true;
3496 bool neg = mstruct.number().isNegative();
3497 Number m(mstruct.number());
3498 m.setNegative(false);
3499 if(SIZE > 1) {
3500 // determine if addition exponentiation should be expanded
3501 // if number of terms and exponent is small enough to allow reasonably fast calculation
3502 if(eo.expand == -1) {
3503 // use more conservative values
3504 switch(SIZE) {
3505 case 4: {if(m.isGreaterThan(3)) {b = false;} break;}
3506 case 3: {if(m.isGreaterThan(4)) {b = false;} break;}
3507 case 2: {if(m.isGreaterThan(10)) {b = false;} break;}
3508 default: {
3509 if(SIZE > 8 || m.isGreaterThan(2)) b = false;
3510 }
3511 }
3512 } else {
3513 b = false;
3514 long int i_pow = m.lintValue(&b);
3515 if(b || i_pow > 300) {
3516 b = false;
3517 } else {
3518 Number num_terms;
3519 if(num_terms.binomial(i_pow + (long int) SIZE - 1, (long int) SIZE - 1)) {
3520 size_t tc = countTotalChildren() / SIZE;
3521 if(tc <= 4) tc = 0;
3522 else tc -= 4;
3523 b = num_terms.isLessThanOrEqualTo(tc > 1 ? 300 / tc : 300);
3524 }
3525 }
3526 }
3527 }
3528 if(b) {
3529 if(!representsNonMatrix()) {
3530 // use simple expansion for base which might be/inlcude matrix(es): (a+b)^n=(a+b)(a+b)...
3531 MathStructure mthis(*this);
3532 while(!m.isOne()) {
3533 if(CALCULATOR->aborted()) {
3534 set(mthis);
3535 goto default_power_merge;
3536 }
3537 calculateMultiply(mthis, eo);
3538 m--;
3539 }
3540 } else {
3541 // use binomial theorem
3542 MathStructure mstruct1(CHILD(0));
3543 MathStructure mstruct2(CHILD(1));
3544 for(size_t i = 2; i < SIZE; i++) {
3545 if(CALCULATOR->aborted()) goto default_power_merge;
3546 mstruct2.add(CHILD(i), true);
3547 }
3548 Number k(1);
3549 Number p1(m);
3550 Number p2(1);
3551 p1--;
3552 Number bn;
3553 MathStructure msave(*this);
3554 CLEAR
3555 APPEND(mstruct1);
3556 CHILD(0).calculateRaise(m, eo);
3557 while(k.isLessThan(m)) {
3558 if(CALCULATOR->aborted() || !bn.binomial(m, k)) {
3559 set(msave);
3560 goto default_power_merge;
3561 }
3562 APPEND_NEW(bn);
3563 LAST.multiply(mstruct1);
3564 if(!p1.isOne()) {
3565 LAST[1].raise_nocopy(new MathStructure(p1));
3566 LAST[1].calculateRaiseExponent(eo);
3567 }
3568 LAST.multiply(mstruct2, true);
3569 if(!p2.isOne()) {
3570 LAST[2].raise_nocopy(new MathStructure(p2));
3571 LAST[2].calculateRaiseExponent(eo);
3572 }
3573 LAST.calculatesub(eo, eo, false);
3574 k++;
3575 p1--;
3576 p2++;
3577 }
3578 APPEND(mstruct2);
3579 LAST.calculateRaise(m, eo);
3580 calculatesub(eo, eo, false);
3581 }
3582 // negative exponent: inverse after expansion (using absolute exponent)
3583 if(neg) calculateInverse(eo);
3584 MERGE_APPROX_AND_PREC(mstruct)
3585 return 1;
3586 }
3587 }
3588 }
3589 goto default_power_merge;
3590 }
3591 case STRUCT_MULTIPLICATION: {
3592 if(mstruct.representsInteger()) {
3593 // (xy)^a=x^a*y^a
3594 for(size_t i = 0; i < SIZE; i++) {
3595 CHILD(i).calculateRaise(mstruct, eo);
3596 }
3597 MERGE_APPROX_AND_PREC(mstruct)
3598 calculatesub(eo, eo, false, mparent, index_this);
3599 return 1;
3600 } else if(!mstruct.isInfinite()) {
3601 // (-5xy)^z=5^z*x^z*(-y)^z && x >= 0 && y<0
3602 MathStructure mnew;
3603 mnew.setType(STRUCT_MULTIPLICATION);
3604 for(size_t i = 0; i < SIZE;) {
3605 if(CHILD(i).representsNonNegative(true)) {
3606 CHILD(i).ref();
3607 mnew.addChild_nocopy(&CHILD(i));
3608 ERASE(i);
3609 } else if(CHILD(i).isNumber() && CHILD(i).number().isNegative() && !CHILD(i).number().isMinusOne()) {
3610 // (-5)^z=5^z*(-1)^z
3611 CHILD(i).number().negate();
3612 mnew.addChild(CHILD(i));
3613 CHILD(i).number().set(-1, 1, 0);
3614 i++;
3615 } else {
3616 i++;
3617 }
3618 }
3619 if(mnew.size() > 0) {
3620 if(SIZE > 0) {
3621 if(SIZE == 1) SET_CHILD_MAP(0)
3622 mnew.addChild(*this);
3623 }
3624 set_nocopy(mnew, true);
3625 for(size_t i = 0; i < SIZE; i++) {
3626 CHILD(i).calculateRaise(mstruct, eo);
3627 }
3628 MERGE_APPROX_AND_PREC(mstruct)
3629 calculatesub(eo, eo, false, mparent, index_this);
3630 return 1;
3631 }
3632 }
3633 goto default_power_merge;
3634 }
3635 case STRUCT_POWER: {
3636 // (x^y)^z
3637 if((eo.allow_complex && CHILD(1).representsFraction()) || (mstruct.representsInteger() && (eo.allow_complex || CHILD(0).representsInteger())) || representsNonNegative(true)) {
3638 // (x^a)^b=x^(a*b) if x>=0 or -1<a<1 or b is integer
3639 if((((!eo.assume_denominators_nonzero || eo.warn_about_denominators_assumed_nonzero) && !CHILD(0).representsNonZero(true)) || CHILD(0).isZero()) && CHILD(1).representsNegative(true)) {
3640 // check that a is positive or x is non-zero
3641 if(!eo.assume_denominators_nonzero || CHILD(0).isZero() || !warn_about_denominators_assumed_nonzero(CHILD(0), eo)) break;
3642 }
3643 if(!CHILD(1).representsNonInteger() && !mstruct.representsInteger()) {
3644 if(CHILD(1).representsEven() && CHILD(0).representsReal(true)) {
3645 // a is even: (x^a)^b=abs(x)^(a*b)
3646 if(CHILD(0).representsNegative(true)) {
3647 CHILD(0).calculateNegate(eo);
3648 } else if(!CHILD(0).representsNonNegative(true)) {
3649 MathStructure mstruct_base(CHILD(0));
3650 CHILD(0).set(CALCULATOR->getFunctionById(FUNCTION_ID_ABS), &mstruct_base, NULL);
3651 }
3652 } else if(!CHILD(1).representsOdd() && !CHILD(0).representsNonNegative(true)) {
3653 // it is not known if a is even or odd (and x might be negative)
3654 goto default_power_merge;
3655 }
3656 }
3657 mstruct.ref();
3658 MERGE_APPROX_AND_PREC(mstruct)
3659 CHILD(1).multiply_nocopy(&mstruct, true);
3660 CHILD(1).calculateMultiplyLast(eo, true, this, 1);
3661 calculateRaiseExponent(eo, mparent, index_this);
3662 return 1;
3663 }
3664 if(mstruct.isNumber() && CHILD(0).isVariable() && CHILD(0).variable()->id() == VARIABLE_ID_E && CHILD(1).isNumber() && CHILD(1).number().hasImaginaryPart() && !CHILD(1).number().hasRealPart() && mstruct.number().isReal()) {
3665 // (e^(a*i))^b
3666 CALCULATOR->beginTemporaryEnableIntervalArithmetic();
3667 if(CALCULATOR->usesIntervalArithmetic()) {
3668 // calculate floor((a+pi)/pi/2) and make sure that upper and lower value is equal
3669 CALCULATOR->beginTemporaryStopMessages();
3670 Number nr(*CHILD(1).number().internalImaginary());
3671 Number nrpi; nrpi.pi();
3672 nr.add(nrpi);
3673 nr.divide(nrpi);
3674 nr.divide(2);
3675 Number nr_u(nr.upperEndPoint());
3676 nr = nr.lowerEndPoint();
3677 nr_u.floor();
3678 nr.floor();
3679 if(!CALCULATOR->endTemporaryStopMessages() && nr == nr_u) {
3680 // (e^(a*i))^b = e^((a-2i*floor((a+pi)/pi/2))*b)
3681 CALCULATOR->endTemporaryEnableIntervalArithmetic();
3682 nr.setApproximate(false);
3683 nr *= 2;
3684 nr.negate();
3685 nr *= nr_one_i;
3686 if(!nr.isZero()) {
3687 CHILD(1) += nr;
3688 CHILD(1).last() *= CALCULATOR->getVariableById(VARIABLE_ID_PI);
3689 }
3690 mstruct.ref();
3691 CHILD(1).multiply_nocopy(&mstruct, true);
3692 CHILD(1).calculateMultiplyLast(eo, true, this, 1);
3693 calculateRaiseExponent(eo, mparent, index_this);
3694 return true;
3695 }
3696 }
3697 CALCULATOR->endTemporaryEnableIntervalArithmetic();
3698 }
3699 goto default_power_merge;
3700 }
3701 case STRUCT_VARIABLE: {
3702 if(o_variable->id() == VARIABLE_ID_E) {
3703 if(mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0].isNumber()) {
3704 if(mstruct[1].isVariable() && mstruct[1].variable()->id() == VARIABLE_ID_PI) {
3705 if(mstruct[0].number().isI() || mstruct[0].number().isMinusI()) {
3706 //e^(i*pi)=-1
3707 set(m_minus_one, true);
3708 return 1;
3709 } else if(mstruct[0].number().hasImaginaryPart() && !mstruct[0].number().hasRealPart() && mstruct[0].number().internalImaginary()->isRational()) {
3710 // e^(a*i*pi)=(-1)^(a)
3711 set(-1, 1, 0, true);
3712 calculateRaise(*mstruct[0].number().internalImaginary(), eo);
3713 MERGE_APPROX_AND_PREC(mstruct)
3714 return 1;
3715 }
3716 } else if(mstruct[0].number().isI() && mstruct[1].isFunction() && mstruct[1].function()->id() == FUNCTION_ID_ATAN && mstruct[1].size() == 1 && !mstruct[1][0].containsUnknowns() && ((eo.expand != 0 && eo.expand > -2) || !mstruct[1][0].containsInterval(true, false, false, eo.expand == -2 ? 1 : 0))) {
3717 //e^(i*atan(x))=(x*i+1)/sqrt(x^2+1)
3718 set(mstruct[1][0], true);
3719 calculateRaise(nr_two, eo);
3720 calculateAdd(m_one, eo);
3721 calculateRaise(nr_half, eo);
3722 calculateInverse(eo);
3723 multiply(mstruct[1][0]);
3724 LAST.calculateMultiply(nr_one_i, eo);
3725 LAST.calculateAdd(m_one, eo);
3726 calculateMultiplyLast(eo);
3727 MERGE_APPROX_AND_PREC(mstruct)
3728 return 1;
3729 }
3730 } else if(mstruct.isFunction() && mstruct.function()->id() == FUNCTION_ID_LOG && mstruct.size() == 1) {
3731 if(mstruct[0].representsNumber() && (eo.allow_infinite || mstruct[0].representsNonZero())) {
3732 // e^ln(x)=x; x!=0
3733 set_nocopy(mstruct[0], true);
3734 return 1;
3735 }
3736 }
3737 }
3738 goto default_power_merge;
3739 }
3740 case STRUCT_FUNCTION: {
3741 if(eo.protected_function != o_function) {
3742 if(o_function->id() == FUNCTION_ID_ABS && SIZE == 1) {
3743 if(mstruct.representsEven() && CHILD(0).representsReal(true)) {
3744 // abs(x)^2=x^2
3745 SET_CHILD_MAP(0);
3746 mstruct.ref();
3747 raise_nocopy(&mstruct);
3748 calculateRaiseExponent(eo);
3749 return 1;
3750 }
3751 } else if(o_function->id() == FUNCTION_ID_SIGNUM && CHILD(0).representsReal(true) && SIZE == 2 && ((CHILD(1).isZero() && mstruct.representsPositive()) || CHILD(1).isOne())) {
3752 if(mstruct.representsOdd()) {
3753 // sgn(x)^3=sgn(x)
3754 MERGE_APPROX_AND_PREC(mstruct)
3755 return 1;
3756 } else if(mstruct.representsEven()) {
3757 if(CHILD(1).isOne() && CHILD(0).representsReal(true)) {
3758 SET_CHILD_MAP(0)
3759 return 1;
3760 } else {
3761 // sgn(x)^2=sgn(abs(x))
3762 CHILD(0).transformById(FUNCTION_ID_ABS);
3763 CHILD_UPDATED(0)
3764 MERGE_APPROX_AND_PREC(mstruct)
3765 return 1;
3766 }
3767 }
3768 } else if(o_function->id() == FUNCTION_ID_ROOT && THIS_VALID_ROOT) {
3769 if(mstruct.representsEven() && CHILD(0).representsReal(true) && CHILD(1).number().isOdd()) {
3770 // root(x, 3)^2=abs(x)^(3/2)
3771 CHILD(0).transformById(FUNCTION_ID_ABS);
3772 CHILD(1).number().recip();
3773 m_type = STRUCT_POWER;
3774 mstruct.ref();
3775 raise_nocopy(&mstruct);
3776 calculateRaiseExponent(eo);
3777 return 1;
3778 } else if(mstruct.isNumber() && mstruct.number().isInteger() && !mstruct.number().isMinusOne()) {
3779 if(mstruct == CHILD(1)) {
3780 // root(x, a)^a=x
3781 SET_CHILD_MAP(0)
3782 MERGE_APPROX_AND_PREC(mstruct)
3783 return 1;
3784 } else if(mstruct.number().isIntegerDivisible(CHILD(1).number())) {
3785 // root(x, a)^(2a)=x^2
3786 mstruct.calculateDivide(CHILD(1).number(), eo);
3787 mstruct.ref();
3788 SET_CHILD_MAP(0)
3789 raise_nocopy(&mstruct);
3790 return 1;
3791 } else if(CHILD(1).number().isIntegerDivisible(mstruct.number())) {
3792 // root(x, 3a)^(a)=root(x, 3)
3793 Number nr(CHILD(1).number());
3794 if(nr.divide(mstruct.number())) {
3795 CHILD(1) = nr;
3796 CHILD_UPDATED(1)
3797 MERGE_APPROX_AND_PREC(mstruct)
3798 return 1;
3799 }
3800 }
3801 }
3802 }
3803 }
3804 if(o_function->id() == FUNCTION_ID_STRIP_UNITS && SIZE == 1 && mstruct.containsType(STRUCT_UNIT, false, true, true) == 0) {
3805 // nounit(x)^y=nounit(x^y)
3806 mstruct.ref();
3807 CHILD(0).raise_nocopy(&mstruct);
3808 return 1;
3809 }
3810 goto default_power_merge;
3811 }
3812 default: {
3813 default_power_merge:
3814
3815 if(mstruct.isAddition()) {
3816 // x^(a+b+...)
3817 bool b = representsNonNegative(true);
3818 if(!b) {
3819 // if x is not >= 0 each term of the exponent must be either an integer
3820 // or, if x<0, a rational number with an even denominator
3821 b = true;
3822 bool bneg = representsNegative(true);
3823 for(size_t i = 0; i < mstruct.size(); i++) {
3824 if(!mstruct[i].representsInteger() && (!bneg || !eo.allow_complex || !mstruct[i].isNumber() || !mstruct[i].number().isRational() || !mstruct[i].number().denominatorIsEven())) {
3825 b = false;
3826 break;
3827 }
3828 }
3829 }
3830 if(b) {
3831 // x^(a+b+...)=x^a*x^b*...
3832 MathStructure msave(*this);
3833 clear(true);
3834 m_type = STRUCT_MULTIPLICATION;
3835 MERGE_APPROX_AND_PREC(mstruct)
3836 for(size_t i = 0; i < mstruct.size(); i++) {
3837 APPEND(msave);
3838 mstruct[i].ref();
3839 LAST.raise_nocopy(&mstruct[i]);
3840 LAST.calculateRaiseExponent(eo);
3841 calculateMultiplyLast(eo, false);
3842 }
3843 if(SIZE == 1) {
3844 setToChild(1, false, mparent, index_this + 1);
3845 } else if(SIZE == 0) {
3846 clear(true);
3847 } else {
3848 evalSort();
3849 }
3850 return 1;
3851 }
3852 } else if(mstruct.isMultiplication() && mstruct.size() > 1) {
3853 // x^(a*b*...)
3854 bool b = representsNonNegative(true);
3855 if(!b) {
3856 // all factors of the exponent must be integers
3857 b = true;
3858 for(size_t i = 0; i < mstruct.size(); i++) {
3859 if(!mstruct[i].representsInteger()) {
3860 b = false;
3861 break;
3862 }
3863 }
3864 }
3865 if(b) {
3866 // try raising the base by each factor separately: x^(a*b*c*...)=(x^a)^(b*c*...))
3867 MathStructure mthis(*this);
3868 for(size_t i = 0; i < mstruct.size(); i++) {
3869 if(i == 0) mthis.raise(mstruct[i]);
3870 // exponent factor must be real and, if base is zero, positive
3871 if(!mstruct[i].representsReal(true) || (isZero() && !mstruct[i].representsPositive(true))) continue;
3872 if(i > 0) mthis[1] = mstruct[i];
3873 EvaluationOptions eo2 = eo;
3874 eo2.split_squares = false;
3875 // avoid abs(x)^(2a) loop
3876 if(mthis.calculateRaiseExponent(eo2) && (!mthis.isPower() || ((!isFunction() || o_function->id() != FUNCTION_ID_ABS || SIZE != 1 || !CHILD(0).equals(mthis[0], true, true)) && (!is_negation(mthis[0], *this))))) {
3877 set(mthis);
3878 if(mstruct.size() == 2) {
3879 if(i == 0) {
3880 mstruct[1].ref();
3881 raise_nocopy(&mstruct[1]);
3882 } else {
3883 mstruct[0].ref();
3884 raise_nocopy(&mstruct[0]);
3885 }
3886 } else {
3887 mstruct.ref();
3888 raise_nocopy(&mstruct);
3889 CHILD(1).delChild(i + 1);
3890 }
3891 calculateRaiseExponent(eo);
3892 MERGE_APPROX_AND_PREC(mstruct)
3893 return 1;
3894 }
3895 }
3896 }
3897 } else if(mstruct.isNumber() && mstruct.number().isRational() && !mstruct.number().isInteger() && !mstruct.number().numeratorIsOne() && !mstruct.number().numeratorIsMinusOne()) {
3898 // x^(n/d)
3899 if(representsNonNegative(true) && (m_type != STRUCT_FUNCTION || o_function->id() != FUNCTION_ID_ABS)) {
3900 // x>0
3901 if(isMultiplication() && SIZE == 2 && CHILD(0).isMinusOne() && mstruct.number().numeratorIsEven()) {
3902 // (-x)^(n/d), n is even
3903 bool b;
3904 if(mstruct.number().isNegative()) {
3905 // n<0: test x^(-n)
3906 MathStructure mtest(CHILD(1));
3907 b = mtest.calculateRaise(-mstruct.number().numerator(), eo);
3908 if(b && mtest.isPower() && mtest[1] == -mstruct.number().numerator()) b = false;
3909 if(!b) break;
3910 // (-x)^(-n/d)=(x^n)^(-1/d)
3911 set(mtest, true);
3912 raise(m_minus_one);
3913 CHILD(1).number() /= mstruct.number().denominator();
3914 } else {
3915 // n>0: test x^n
3916 MathStructure mtest(CHILD(1));
3917 b = mtest.calculateRaise(mstruct.number().numerator(), eo);
3918 if(b && mtest.isPower() && mtest[1] == mstruct.number().numerator()) b = false;
3919 if(!b) break;
3920 // (-x)^(n/d)=(x^n)^(1/d)
3921 set(mtest, true);
3922 raise(m_one);
3923 CHILD(1).number() /= mstruct.number().denominator();
3924 }
3925 if(b) calculateRaiseExponent(eo);
3926 return 1;
3927 }
3928 bool b;
3929 if(mstruct.number().isNegative()) {
3930 // try x^(-n/d)=(x^n)^(-1/d)
3931 b = calculateRaise(-mstruct.number().numerator(), eo);
3932 if(!b) {
3933 setToChild(1);
3934 break;
3935 }
3936 raise(m_minus_one);
3937 CHILD(1).number() /= mstruct.number().denominator();
3938 } else {
3939 // try x^(n/d)=(x^n)^(1/d)
3940 b = calculateRaise(mstruct.number().numerator(), eo);
3941 if(!b) {
3942 setToChild(1);
3943 break;
3944 }
3945 raise(m_one);
3946 CHILD(1).number() /= mstruct.number().denominator();
3947 }
3948 if(b) calculateRaiseExponent(eo);
3949 return 1;
3950 }
3951 }
3952 break;
3953 }
3954 }
3955
3956 return -1;
3957 }
3958
merge_logical_and(MathStructure & mstruct,const EvaluationOptions & eo,MathStructure * mparent,size_t index_this,size_t index_mstruct,bool)3959 int MathStructure::merge_logical_and(MathStructure &mstruct, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this, size_t index_mstruct, bool) {
3960 if(equals(mstruct, true, true)) {
3961 MERGE_APPROX_AND_PREC(mstruct)
3962 return 2;
3963 }
3964 if(mstruct.representsNonZero()) {
3965 MERGE_APPROX_AND_PREC(mstruct)
3966 return 2;
3967 }
3968 if(mstruct.isZero()) {
3969 if(isZero()) return 2;
3970 clear(true);
3971 MERGE_APPROX_AND_PREC(mstruct)
3972 return 3;
3973 }
3974 if(representsNonZero()) {
3975 if(mparent) {
3976 mparent->swapChildren(index_this + 1, index_mstruct + 1);
3977 } else {
3978 set_nocopy(mstruct, true);
3979 }
3980 return 3;
3981 }
3982 if(isZero()) {
3983 MERGE_APPROX_AND_PREC(mstruct)
3984 return 2;
3985 }
3986
3987 if(CALCULATOR->aborted()) return -1;
3988
3989 if(eo.test_comparisons && isLogicalOr()) {
3990 if(SIZE > 50) return -1;
3991 if(mstruct.isLogicalOr()) {
3992 if(mstruct.size() * SIZE > 50) return -1;
3993 for(size_t i = 0; i < SIZE; ) {
3994 MathStructure msave(CHILD(i));
3995 for(size_t i2 = 0; i2 < mstruct.size(); i2++) {
3996 if(i2 > 0) {
3997 insertChild(msave, i + 1);
3998 }
3999 CHILD(i).calculateLogicalAnd(mstruct[i2], eo, this, i);
4000 i++;
4001 }
4002 }
4003 } else {
4004 for(size_t i = 0; i < SIZE; i++) {
4005 CHILD(i).calculateLogicalAnd(mstruct, eo, this, i);
4006 }
4007 }
4008 MERGE_APPROX_AND_PREC(mstruct)
4009 calculatesub(eo, eo, false);
4010 return 1;
4011 } else if(eo.test_comparisons && mstruct.isLogicalOr()) {
4012 return 0;
4013 } else if(isComparison() && mstruct.isComparison()) {
4014 if(CHILD(0) == mstruct[0]) {
4015 ComparisonResult cr = mstruct[1].compare(CHILD(1));
4016 ComparisonType ct1 = ct_comp, ct2 = mstruct.comparisonType();
4017 switch(cr) {
4018 case COMPARISON_RESULT_NOT_EQUAL: {
4019 if(ct_comp == COMPARISON_EQUALS && ct2 == COMPARISON_EQUALS) {
4020 clear(true);
4021 MERGE_APPROX_AND_PREC(mstruct)
4022 return 1;
4023 } else if(ct_comp == COMPARISON_EQUALS && ct2 == COMPARISON_NOT_EQUALS) {
4024 MERGE_APPROX_AND_PREC(mstruct)
4025 return 2;
4026 } else if(ct_comp == COMPARISON_NOT_EQUALS && ct2 == COMPARISON_EQUALS) {
4027 if(mparent) {
4028 mparent->swapChildren(index_this + 1, index_mstruct + 1);
4029 } else {
4030 set_nocopy(mstruct, true);
4031 }
4032 return 3;
4033 }
4034 return -1;
4035 }
4036 case COMPARISON_RESULT_EQUAL: {
4037 MERGE_APPROX_AND_PREC(mstruct)
4038 if(ct_comp == ct2) return 1;
4039 if(ct_comp == COMPARISON_NOT_EQUALS) {
4040 if(ct2 == COMPARISON_LESS || ct2 == COMPARISON_EQUALS_LESS) {
4041 ct_comp = COMPARISON_LESS;
4042 if(ct2 == COMPARISON_LESS) return 3;
4043 return 1;
4044 } else if(ct2 == COMPARISON_GREATER || ct2 == COMPARISON_EQUALS_GREATER) {
4045 ct_comp = COMPARISON_GREATER;
4046 if(ct2 == COMPARISON_GREATER) return 3;
4047 return 1;
4048 }
4049 } else if(ct2 == COMPARISON_NOT_EQUALS) {
4050 if(ct_comp == COMPARISON_LESS || ct_comp == COMPARISON_EQUALS_LESS) {
4051 if(ct_comp == COMPARISON_LESS) return 2;
4052 ct_comp = COMPARISON_LESS;
4053 return 1;
4054 } else if(ct_comp == COMPARISON_GREATER || ct_comp == COMPARISON_EQUALS_GREATER) {
4055 if(ct_comp == COMPARISON_GREATER) return 2;
4056 ct_comp = COMPARISON_GREATER;
4057 return 1;
4058 }
4059 } else if((ct_comp == COMPARISON_EQUALS_LESS || ct_comp == COMPARISON_EQUALS_GREATER || ct_comp == COMPARISON_EQUALS) && (ct2 == COMPARISON_EQUALS_LESS || ct2 == COMPARISON_EQUALS_GREATER || ct2 == COMPARISON_EQUALS)) {
4060 if(ct_comp == COMPARISON_EQUALS) return 2;
4061 ct_comp = COMPARISON_EQUALS;
4062 if(ct2 == COMPARISON_EQUALS) return 3;
4063 return 1;
4064 } else if((ct_comp == COMPARISON_LESS || ct_comp == COMPARISON_EQUALS_LESS) && (ct2 == COMPARISON_LESS || ct2 == COMPARISON_EQUALS_LESS)) {
4065 if(ct_comp == COMPARISON_LESS) return 2;
4066 ct_comp = COMPARISON_LESS;
4067 if(ct2 == COMPARISON_LESS) return 3;
4068 return 1;
4069 } else if((ct_comp == COMPARISON_GREATER || ct_comp == COMPARISON_EQUALS_GREATER) && (ct2 == COMPARISON_GREATER || ct2 == COMPARISON_EQUALS_GREATER)) {
4070 if(ct_comp == COMPARISON_GREATER) return 2;
4071 ct_comp = COMPARISON_GREATER;
4072 if(ct2 == COMPARISON_GREATER) return 3;
4073 return 1;
4074 }
4075 clear(true);
4076 return 1;
4077 }
4078 case COMPARISON_RESULT_EQUAL_OR_GREATER: {
4079 switch(ct1) {
4080 case COMPARISON_GREATER: {ct1 = COMPARISON_LESS; break;}
4081 case COMPARISON_EQUALS_GREATER: {ct1 = COMPARISON_EQUALS_LESS; break;}
4082 case COMPARISON_LESS: {ct1 = COMPARISON_GREATER; break;}
4083 case COMPARISON_EQUALS_LESS: {ct1 = COMPARISON_EQUALS_GREATER; break;}
4084 default: {}
4085 }
4086 switch(ct2) {
4087 case COMPARISON_GREATER: {ct2 = COMPARISON_LESS; break;}
4088 case COMPARISON_EQUALS_GREATER: {ct2 = COMPARISON_EQUALS_LESS; break;}
4089 case COMPARISON_LESS: {ct2 = COMPARISON_GREATER; break;}
4090 case COMPARISON_EQUALS_LESS: {ct2 = COMPARISON_EQUALS_GREATER; break;}
4091 default: {}
4092 }
4093 }
4094 case COMPARISON_RESULT_EQUAL_OR_LESS: {
4095 switch(ct1) {
4096 case COMPARISON_LESS: {
4097 if(ct2 == COMPARISON_GREATER || ct2 == COMPARISON_EQUALS) {
4098 clear(true);
4099 MERGE_APPROX_AND_PREC(mstruct)
4100 return 1;
4101 } else if(ct2 == COMPARISON_LESS || ct2 == COMPARISON_EQUALS_LESS || ct2 == COMPARISON_NOT_EQUALS) {
4102 MERGE_APPROX_AND_PREC(mstruct)
4103 return 2;
4104 }
4105 break;
4106 }
4107 case COMPARISON_GREATER: {
4108 if(ct2 == COMPARISON_GREATER) {
4109 if(mparent) {
4110 mparent->swapChildren(index_this + 1, index_mstruct + 1);
4111 } else {
4112 set_nocopy(mstruct, true);
4113 }
4114 return 3;
4115 }
4116 break;
4117 }
4118 case COMPARISON_EQUALS_LESS: {
4119 if(ct2 == COMPARISON_EQUALS_LESS) {
4120 MERGE_APPROX_AND_PREC(mstruct)
4121 return 2;
4122 }
4123 break;
4124 }
4125 case COMPARISON_EQUALS_GREATER: {
4126 if(ct2 == COMPARISON_EQUALS_GREATER || ct2 == COMPARISON_EQUALS) {
4127 if(mparent) {
4128 mparent->swapChildren(index_this + 1, index_mstruct + 1);
4129 } else {
4130 set_nocopy(mstruct, true);
4131 }
4132 return 3;
4133 }
4134 break;
4135 }
4136 case COMPARISON_EQUALS: {
4137 if(ct2 == COMPARISON_GREATER) {
4138 clear(true);
4139 MERGE_APPROX_AND_PREC(mstruct)
4140 return 1;
4141 }
4142 break;
4143 }
4144 case COMPARISON_NOT_EQUALS: {
4145 if(ct2 == COMPARISON_GREATER) {
4146 if(mparent) {
4147 mparent->swapChildren(index_this + 1, index_mstruct + 1);
4148 } else {
4149 set_nocopy(mstruct, true);
4150 }
4151 return 3;
4152 }
4153 break;
4154 }
4155 }
4156 break;
4157 }
4158 case COMPARISON_RESULT_GREATER: {
4159 switch(ct1) {
4160 case COMPARISON_GREATER: {ct1 = COMPARISON_LESS; break;}
4161 case COMPARISON_EQUALS_GREATER: {ct1 = COMPARISON_EQUALS_LESS; break;}
4162 case COMPARISON_LESS: {ct1 = COMPARISON_GREATER; break;}
4163 case COMPARISON_EQUALS_LESS: {ct1 = COMPARISON_EQUALS_GREATER; break;}
4164 default: {}
4165 }
4166 switch(ct2) {
4167 case COMPARISON_GREATER: {ct2 = COMPARISON_LESS; break;}
4168 case COMPARISON_EQUALS_GREATER: {ct2 = COMPARISON_EQUALS_LESS; break;}
4169 case COMPARISON_LESS: {ct2 = COMPARISON_GREATER; break;}
4170 case COMPARISON_EQUALS_LESS: {ct2 = COMPARISON_EQUALS_GREATER; break;}
4171 default: {}
4172 }
4173 }
4174 case COMPARISON_RESULT_LESS: {
4175 switch(ct1) {
4176 case COMPARISON_EQUALS: {
4177 switch(ct2) {
4178 case COMPARISON_EQUALS: {}
4179 case COMPARISON_EQUALS_GREATER: {}
4180 case COMPARISON_GREATER: {MERGE_APPROX_AND_PREC(mstruct) clear(true); return 1;}
4181 case COMPARISON_NOT_EQUALS: {}
4182 case COMPARISON_EQUALS_LESS: {}
4183 case COMPARISON_LESS: {MERGE_APPROX_AND_PREC(mstruct) return 2;}
4184 default: {}
4185 }
4186 break;
4187 }
4188 case COMPARISON_NOT_EQUALS: {
4189 switch(ct2) {
4190 case COMPARISON_EQUALS: {}
4191 case COMPARISON_EQUALS_GREATER: {}
4192 case COMPARISON_GREATER: {
4193 if(mparent) {
4194 mparent->swapChildren(index_this + 1, index_mstruct + 1);
4195 } else {
4196 set_nocopy(mstruct, true);
4197 }
4198 return 3;
4199 }
4200 default: {}
4201 }
4202 break;
4203 }
4204 case COMPARISON_EQUALS_LESS: {}
4205 case COMPARISON_LESS: {
4206 switch(ct2) {
4207 case COMPARISON_EQUALS: {}
4208 case COMPARISON_EQUALS_GREATER: {}
4209 case COMPARISON_GREATER: {MERGE_APPROX_AND_PREC(mstruct) clear(true); return 1;}
4210 case COMPARISON_NOT_EQUALS: {}
4211 case COMPARISON_EQUALS_LESS: {}
4212 case COMPARISON_LESS: {MERGE_APPROX_AND_PREC(mstruct) return 2;}
4213 }
4214 break;
4215 }
4216 case COMPARISON_EQUALS_GREATER: {}
4217 case COMPARISON_GREATER: {
4218 switch(ct2) {
4219 case COMPARISON_EQUALS: {}
4220 case COMPARISON_EQUALS_GREATER: {}
4221 case COMPARISON_GREATER: {
4222 if(mparent) {
4223 mparent->swapChildren(index_this + 1, index_mstruct + 1);
4224 } else {
4225 set_nocopy(mstruct, true);
4226 }
4227 return 3;
4228 }
4229 default: {}
4230 }
4231 break;
4232 }
4233 }
4234 break;
4235 }
4236 default: {
4237 if(!eo.test_comparisons) return -1;
4238 if(comparisonType() == COMPARISON_EQUALS && !CHILD(1).contains(mstruct[0])) {
4239 mstruct.calculateReplace(CHILD(0), CHILD(1), eo);
4240 if(eo.isolate_x) {mstruct.isolate_x(eo, eo); mstruct.calculatesub(eo, eo, true);}
4241 mstruct.ref();
4242 add_nocopy(&mstruct, OPERATION_LOGICAL_AND);
4243 calculateLogicalAndLast(eo);
4244 return 1;
4245 } else if(mstruct.comparisonType() == COMPARISON_EQUALS && !mstruct[1].contains(CHILD(0))) {
4246 calculateReplace(mstruct[0], mstruct[1], eo);
4247 if(eo.isolate_x) {isolate_x(eo, eo); calculatesub(eo, eo, true);}
4248 mstruct.ref();
4249 add_nocopy(&mstruct, OPERATION_LOGICAL_AND);
4250 calculateLogicalAndLast(eo);
4251 return 1;
4252 }
4253 return -1;
4254 }
4255 }
4256 } else if(eo.test_comparisons && comparisonType() == COMPARISON_EQUALS && !CHILD(0).isNumber() && !CHILD(0).containsInterval() && CHILD(1).isNumber() && mstruct.contains(CHILD(0))) {
4257 mstruct.calculateReplace(CHILD(0), CHILD(1), eo);
4258 if(eo.isolate_x) {mstruct.isolate_x(eo, eo); mstruct.calculatesub(eo, eo, true);}
4259 mstruct.ref();
4260 add_nocopy(&mstruct, OPERATION_LOGICAL_AND);
4261 calculateLogicalAndLast(eo);
4262 return 1;
4263 } else if(eo.test_comparisons && mstruct.comparisonType() == COMPARISON_EQUALS && !mstruct[0].isNumber() && !mstruct[0].containsInterval() && mstruct[1].isNumber() && contains(mstruct[0])) {
4264 calculateReplace(mstruct[0], mstruct[1], eo);
4265 if(eo.isolate_x) {isolate_x(eo, eo); calculatesub(eo, eo, true);}
4266 mstruct.ref();
4267 add_nocopy(&mstruct, OPERATION_LOGICAL_AND);
4268 calculateLogicalAndLast(eo);
4269 return 1;
4270 }
4271 } else if(isLogicalAnd()) {
4272 if(mstruct.isLogicalAnd()) {
4273 for(size_t i = 0; i < mstruct.size(); i++) {
4274 APPEND_REF(&mstruct[i]);
4275 }
4276 MERGE_APPROX_AND_PREC(mstruct)
4277 calculatesub(eo, eo, false);
4278 } else {
4279 APPEND_REF(&mstruct);
4280 MERGE_APPROX_AND_PREC(mstruct)
4281 calculatesub(eo, eo, false);
4282 }
4283 return 1;
4284 } else if(mstruct.isLogicalAnd()) {
4285 transform(STRUCT_LOGICAL_AND);
4286 for(size_t i = 0; i < mstruct.size(); i++) {
4287 APPEND_REF(&mstruct[i]);
4288 }
4289 MERGE_APPROX_AND_PREC(mstruct)
4290 calculatesub(eo, eo, false);
4291 return 1;
4292 }
4293 return -1;
4294
4295 }
4296
merge_logical_or(MathStructure & mstruct,const EvaluationOptions & eo,MathStructure * mparent,size_t index_this,size_t index_mstruct,bool)4297 int MathStructure::merge_logical_or(MathStructure &mstruct, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this, size_t index_mstruct, bool) {
4298
4299 if(mstruct.representsNonZero()) {
4300 if(isOne()) {
4301 MERGE_APPROX_AND_PREC(mstruct)
4302 return 2;
4303 }
4304 set(1, 1, 0, true);
4305 MERGE_APPROX_AND_PREC(mstruct)
4306 return 3;
4307 }
4308 if(mstruct.isZero()) {
4309 MERGE_APPROX_AND_PREC(mstruct)
4310 return 2;
4311 }
4312 if(representsNonZero()) {
4313 if(!isOne()) set(1, 1, 0, true);
4314 MERGE_APPROX_AND_PREC(mstruct)
4315 return 2;
4316 }
4317 if(isZero()) {
4318 if(mparent) {
4319 mparent->swapChildren(index_this + 1, index_mstruct + 1);
4320 } else {
4321 set_nocopy(mstruct, true);
4322 }
4323 return 3;
4324 }
4325 if(equals(mstruct, true, true)) {
4326 return 2;
4327 }
4328 if(isLogicalAnd()) {
4329 if(mstruct.isLogicalAnd()) {
4330 if(SIZE < mstruct.size()) {
4331 bool b = true;
4332 for(size_t i = 0; i < SIZE; i++) {
4333 b = false;
4334 for(size_t i2 = 0; i2 < mstruct.size(); i2++) {
4335 if(CHILD(i) == mstruct[i2]) {
4336 b = true;
4337 break;
4338 }
4339 }
4340 if(!b) break;
4341 }
4342 if(b) {
4343 MERGE_APPROX_AND_PREC(mstruct)
4344 return 2;
4345 }
4346 } else if(SIZE > mstruct.size()) {
4347 bool b = true;
4348 for(size_t i = 0; i < mstruct.size(); i++) {
4349 b = false;
4350 for(size_t i2 = 0; i2 < SIZE; i2++) {
4351 if(mstruct[i] == CHILD(i2)) {
4352 b = true;
4353 break;
4354 }
4355 }
4356 if(!b) break;
4357 }
4358 if(b) {
4359 if(mparent) {
4360 mparent->swapChildren(index_this + 1, index_mstruct + 1);
4361 } else {
4362 set_nocopy(mstruct, true);
4363 }
4364 return 3;
4365 }
4366 }
4367 } else {
4368 for(size_t i = 0; i < SIZE; i++) {
4369 if(CHILD(i) == mstruct) {
4370 if(mparent) {
4371 mparent->swapChildren(index_this + 1, index_mstruct + 1);
4372 } else {
4373 set_nocopy(mstruct, true);
4374 }
4375 return 3;
4376 }
4377 }
4378 }
4379 } else if(mstruct.isLogicalAnd()) {
4380 for(size_t i = 0; i < mstruct.size(); i++) {
4381 if(equals(mstruct[i])) {
4382 MERGE_APPROX_AND_PREC(mstruct)
4383 return 2;
4384 }
4385 }
4386 }
4387
4388 if(isComparison() && mstruct.isComparison()) {
4389 if(CHILD(0) == mstruct[0]) {
4390 ComparisonResult cr = mstruct[1].compare(CHILD(1));
4391 ComparisonType ct1 = ct_comp, ct2 = mstruct.comparisonType();
4392 switch(cr) {
4393 case COMPARISON_RESULT_NOT_EQUAL: {
4394 return -1;
4395 }
4396 case COMPARISON_RESULT_EQUAL: {
4397 if(ct_comp == ct2) return 1;
4398 switch(ct_comp) {
4399 case COMPARISON_EQUALS: {
4400 switch(ct2) {
4401 case COMPARISON_NOT_EQUALS: {set(1, 1, 0, true); MERGE_APPROX_AND_PREC(mstruct) return 1;}
4402 case COMPARISON_EQUALS_LESS: {}
4403 case COMPARISON_EQUALS_GREATER: {ct_comp = ct2; MERGE_APPROX_AND_PREC(mstruct) return 3;}
4404 case COMPARISON_LESS: {ct_comp = COMPARISON_EQUALS_LESS; MERGE_APPROX_AND_PREC(mstruct) return 1;}
4405 case COMPARISON_GREATER: {ct_comp = COMPARISON_EQUALS_GREATER; MERGE_APPROX_AND_PREC(mstruct) return 1;}
4406 default: {}
4407 }
4408 break;
4409 }
4410 case COMPARISON_NOT_EQUALS: {
4411 switch(ct2) {
4412 case COMPARISON_EQUALS_LESS: {}
4413 case COMPARISON_EQUALS_GREATER: {}
4414 case COMPARISON_EQUALS: {set(1, 1, 0, true); MERGE_APPROX_AND_PREC(mstruct) return 1;}
4415 case COMPARISON_LESS: {}
4416 case COMPARISON_GREATER: {MERGE_APPROX_AND_PREC(mstruct) return 2;}
4417 default: {}
4418 }
4419 break;
4420 }
4421 case COMPARISON_EQUALS_LESS: {
4422 switch(ct2) {
4423 case COMPARISON_NOT_EQUALS: {}
4424 case COMPARISON_GREATER: {}
4425 case COMPARISON_EQUALS_GREATER: {set(1, 1, 0, true); MERGE_APPROX_AND_PREC(mstruct) return 1;}
4426 case COMPARISON_EQUALS: {}
4427 case COMPARISON_LESS: {MERGE_APPROX_AND_PREC(mstruct) return 2;}
4428 default: {}
4429 }
4430 break;
4431 }
4432 case COMPARISON_LESS: {
4433 switch(ct2) {
4434 case COMPARISON_NOT_EQUALS: {}
4435 case COMPARISON_EQUALS_LESS: {ct_comp = ct2; MERGE_APPROX_AND_PREC(mstruct) return 3;}
4436 case COMPARISON_EQUALS_GREATER: {set(1, 1, 0, true); MERGE_APPROX_AND_PREC(mstruct) return 1;}
4437 case COMPARISON_EQUALS: {ct_comp = COMPARISON_EQUALS_LESS; MERGE_APPROX_AND_PREC(mstruct) return 1;}
4438 case COMPARISON_GREATER: {ct_comp = COMPARISON_NOT_EQUALS; MERGE_APPROX_AND_PREC(mstruct) return 1;}
4439 default: {}
4440 }
4441 break;
4442 }
4443 case COMPARISON_EQUALS_GREATER: {
4444 switch(ct2) {
4445 case COMPARISON_NOT_EQUALS: {}
4446 case COMPARISON_LESS: {}
4447 case COMPARISON_EQUALS_LESS: {set(1, 1, 0, true); MERGE_APPROX_AND_PREC(mstruct) return 1;}
4448 case COMPARISON_EQUALS: {}
4449 case COMPARISON_GREATER: {MERGE_APPROX_AND_PREC(mstruct) return 2;}
4450 default: {}
4451 }
4452 break;
4453 }
4454 case COMPARISON_GREATER: {
4455 switch(ct2) {
4456 case COMPARISON_NOT_EQUALS: {}
4457 case COMPARISON_EQUALS_GREATER: {ct_comp = ct2; MERGE_APPROX_AND_PREC(mstruct) return 3;}
4458 case COMPARISON_EQUALS_LESS: {set(1, 1, 0, true); MERGE_APPROX_AND_PREC(mstruct) return 1;}
4459 case COMPARISON_EQUALS: {ct_comp = COMPARISON_EQUALS_GREATER; MERGE_APPROX_AND_PREC(mstruct) return 1;}
4460 case COMPARISON_LESS: {ct_comp = COMPARISON_NOT_EQUALS; MERGE_APPROX_AND_PREC(mstruct) return 1;}
4461 default: {}
4462 }
4463 break;
4464 }
4465 }
4466 break;
4467 }
4468 case COMPARISON_RESULT_EQUAL_OR_GREATER: {
4469 switch(ct1) {
4470 case COMPARISON_GREATER: {ct1 = COMPARISON_LESS; break;}
4471 case COMPARISON_EQUALS_GREATER: {ct1 = COMPARISON_EQUALS_LESS; break;}
4472 case COMPARISON_LESS: {ct1 = COMPARISON_GREATER; break;}
4473 case COMPARISON_EQUALS_LESS: {ct1 = COMPARISON_EQUALS_GREATER; break;}
4474 default: {}
4475 }
4476 switch(ct2) {
4477 case COMPARISON_GREATER: {ct2 = COMPARISON_LESS; break;}
4478 case COMPARISON_EQUALS_GREATER: {ct2 = COMPARISON_EQUALS_LESS; break;}
4479 case COMPARISON_LESS: {ct2 = COMPARISON_GREATER; break;}
4480 case COMPARISON_EQUALS_LESS: {ct2 = COMPARISON_EQUALS_GREATER; break;}
4481 default: {}
4482 }
4483 }
4484 case COMPARISON_RESULT_EQUAL_OR_LESS: {
4485 switch(ct1) {
4486 case COMPARISON_LESS: {
4487 if(ct2 == COMPARISON_LESS || ct2 == COMPARISON_EQUALS_LESS || ct2 == COMPARISON_NOT_EQUALS) {
4488 if(mparent) {
4489 mparent->swapChildren(index_this + 1, index_mstruct + 1);
4490 } else {
4491 set_nocopy(mstruct, true);
4492 }
4493 return 3;
4494 }
4495 break;
4496 }
4497 case COMPARISON_GREATER: {
4498 if(ct2 == COMPARISON_GREATER) {
4499 MERGE_APPROX_AND_PREC(mstruct)
4500 return 2;
4501 }
4502 break;
4503 }
4504 case COMPARISON_EQUALS_LESS: {
4505 if(ct2 == COMPARISON_EQUALS_LESS) {
4506 if(mparent) {
4507 mparent->swapChildren(index_this + 1, index_mstruct + 1);
4508 } else {
4509 set_nocopy(mstruct, true);
4510 }
4511 return 3;
4512 }
4513 break;
4514 }
4515 case COMPARISON_EQUALS_GREATER: {
4516 if(ct2 == COMPARISON_EQUALS_GREATER || ct2 == COMPARISON_EQUALS) {
4517 MERGE_APPROX_AND_PREC(mstruct)
4518 return 2;
4519 }
4520 break;
4521 }
4522 case COMPARISON_NOT_EQUALS: {
4523 if(ct2 == COMPARISON_GREATER) {
4524 MERGE_APPROX_AND_PREC(mstruct)
4525 return 2;
4526 }
4527 break;
4528 }
4529 default: {}
4530 }
4531 break;
4532 }
4533 case COMPARISON_RESULT_GREATER: {
4534 switch(ct1) {
4535 case COMPARISON_GREATER: {ct1 = COMPARISON_LESS; break;}
4536 case COMPARISON_EQUALS_GREATER: {ct1 = COMPARISON_EQUALS_LESS; break;}
4537 case COMPARISON_LESS: {ct1 = COMPARISON_GREATER; break;}
4538 case COMPARISON_EQUALS_LESS: {ct1 = COMPARISON_EQUALS_GREATER; break;}
4539 default: {}
4540 }
4541 switch(ct2) {
4542 case COMPARISON_GREATER: {ct2 = COMPARISON_LESS; break;}
4543 case COMPARISON_EQUALS_GREATER: {ct2 = COMPARISON_EQUALS_LESS; break;}
4544 case COMPARISON_LESS: {ct2 = COMPARISON_GREATER; break;}
4545 case COMPARISON_EQUALS_LESS: {ct2 = COMPARISON_EQUALS_GREATER; break;}
4546 default: {}
4547 }
4548 }
4549 case COMPARISON_RESULT_LESS: {
4550 switch(ct1) {
4551 case COMPARISON_EQUALS: {
4552 switch(ct2) {
4553 case COMPARISON_NOT_EQUALS: {}
4554 case COMPARISON_EQUALS_LESS: {}
4555 case COMPARISON_LESS: {
4556 if(mparent) {
4557 mparent->swapChildren(index_this + 1, index_mstruct + 1);
4558 } else {
4559 set_nocopy(mstruct, true);
4560 }
4561 return 3;
4562 }
4563 default: {}
4564 }
4565 break;
4566 }
4567 case COMPARISON_NOT_EQUALS: {
4568 switch(ct2) {
4569 case COMPARISON_EQUALS: {}
4570 case COMPARISON_EQUALS_GREATER: {}
4571 case COMPARISON_GREATER: {MERGE_APPROX_AND_PREC(mstruct) return 2;}
4572 case COMPARISON_EQUALS_LESS: {}
4573 case COMPARISON_LESS: {set(1, 1, 0, true); MERGE_APPROX_AND_PREC(mstruct) return 1;}
4574 default: {}
4575 }
4576 break;
4577 }
4578 case COMPARISON_EQUALS_LESS: {}
4579 case COMPARISON_LESS: {
4580 switch(ct2) {
4581 case COMPARISON_NOT_EQUALS: {}
4582 case COMPARISON_EQUALS_LESS: {}
4583 case COMPARISON_LESS: {
4584 if(mparent) {
4585 mparent->swapChildren(index_this + 1, index_mstruct + 1);
4586 } else {
4587 set_nocopy(mstruct, true);
4588 }
4589 return 3;
4590 }
4591 default: {}
4592 }
4593 break;
4594 }
4595 case COMPARISON_EQUALS_GREATER: {}
4596 case COMPARISON_GREATER: {
4597 switch(ct2) {
4598 case COMPARISON_NOT_EQUALS: {}
4599 case COMPARISON_EQUALS_LESS: {}
4600 case COMPARISON_LESS: {set(1, 1, 0, true); MERGE_APPROX_AND_PREC(mstruct) return 1;}
4601 case COMPARISON_EQUALS: {}
4602 case COMPARISON_EQUALS_GREATER: {}
4603 case COMPARISON_GREATER: {MERGE_APPROX_AND_PREC(mstruct) return 2;}
4604 }
4605 break;
4606 }
4607 }
4608 break;
4609 }
4610 default: {
4611 return -1;
4612 }
4613 }
4614 } else if(eo.test_comparisons && comparisonType() == COMPARISON_NOT_EQUALS && !CHILD(0).isNumber() && !CHILD(0).containsInterval() && CHILD(1).isNumber() && mstruct.contains(CHILD(0))) {
4615 mstruct.calculateReplace(CHILD(0), CHILD(1), eo);
4616 if(eo.isolate_x) {mstruct.isolate_x(eo, eo); mstruct.calculatesub(eo, eo, true);}
4617 mstruct.ref();
4618 add_nocopy(&mstruct, OPERATION_LOGICAL_OR);
4619 calculateLogicalOrLast(eo);
4620 return 1;
4621 } else if(eo.test_comparisons && mstruct.comparisonType() == COMPARISON_NOT_EQUALS && !mstruct[0].isNumber() && !mstruct[0].containsInterval() && mstruct[1].isNumber() && contains(mstruct[0])) {
4622 calculateReplace(mstruct[0], mstruct[1], eo);
4623 if(eo.isolate_x) {isolate_x(eo, eo); calculatesub(eo, eo, true);}
4624 mstruct.ref();
4625 add_nocopy(&mstruct, OPERATION_LOGICAL_OR);
4626 calculateLogicalOrLast(eo);
4627 return 1;
4628 }
4629 } else if(isLogicalOr()) {
4630 if(mstruct.isLogicalOr()) {
4631 for(size_t i = 0; i < mstruct.size(); i++) {
4632 APPEND_REF(&mstruct[i]);
4633 }
4634 MERGE_APPROX_AND_PREC(mstruct)
4635 calculatesub(eo, eo, false);
4636 } else {
4637 APPEND_REF(&mstruct);
4638 MERGE_APPROX_AND_PREC(mstruct)
4639 calculatesub(eo, eo, false);
4640 }
4641 return 1;
4642 } else if(mstruct.isLogicalOr()) {
4643 transform(STRUCT_LOGICAL_OR);
4644 for(size_t i = 0; i < mstruct.size(); i++) {
4645 APPEND_REF(&mstruct[i]);
4646 }
4647 MERGE_APPROX_AND_PREC(mstruct)
4648 calculatesub(eo, eo, false);
4649 return 1;
4650 }
4651 return -1;
4652
4653 }
4654
merge_logical_xor(MathStructure & mstruct,const EvaluationOptions & eo,MathStructure *,size_t,size_t,bool)4655 int MathStructure::merge_logical_xor(MathStructure &mstruct, const EvaluationOptions &eo, MathStructure*, size_t, size_t, bool) {
4656
4657 if(equals(mstruct)) {
4658 clear(true);
4659 MERGE_APPROX_AND_PREC(mstruct)
4660 return 1;
4661 }
4662 bool bp1 = representsNonZero();
4663 bool bp2 = mstruct.representsNonZero();
4664 if(bp1 && bp2) {
4665 clear(true);
4666 MERGE_APPROX_AND_PREC(mstruct)
4667 return 1;
4668 }
4669 bool bn1 = isZero();
4670 bool bn2 = mstruct.isZero();
4671 if(bn1 && bn2) {
4672 clear(true);
4673 MERGE_APPROX_AND_PREC(mstruct)
4674 return 1;
4675 }
4676 if((bn1 && bp2) || (bp1 && bn2)) {
4677 set(1, 1, 0, true);
4678 MERGE_APPROX_AND_PREC(mstruct)
4679 return 1;
4680 }
4681 return -1;
4682
4683 /*int b0, b1;
4684 if(isZero()) {
4685 b0 = 0;
4686 } else if(representsNonZero(true)) {
4687 b0 = 1;
4688 } else {
4689 b0 = -1;
4690 }
4691 if(mstruct.isZero()) {
4692 b1 = 0;
4693 } else if(mstruct.representsNonZero(true)) {
4694 b1 = 1;
4695 } else {
4696 b1 = -1;
4697 }
4698
4699 if((b0 == 1 && b1 == 0) || (b0 == 0 && b1 == 1)) {
4700 set(1, 1, 0, true);
4701 MERGE_APPROX_AND_PREC(mstruct)
4702 return 1;
4703 } else if(b0 >= 0 && b1 >= 0) {
4704 clear(true);
4705 MERGE_APPROX_AND_PREC(mstruct)
4706 return 1;
4707 } else if(b0 == 0) {
4708 set(mstruct, true);
4709 add(m_zero, OPERATION_NOT_EQUALS);
4710 calculatesub(eo, eo, false);
4711 return 1;
4712 } else if(b0 == 1) {
4713 set(mstruct, true);
4714 add(m_zero, OPERATION_EQUALS);
4715 calculatesub(eo, eo, false);
4716 return 1;
4717 } else if(b1 == 0) {
4718 add(m_zero, OPERATION_NOT_EQUALS);
4719 calculatesub(eo, eo, false);
4720 MERGE_APPROX_AND_PREC(mstruct)
4721 return 1;
4722 } else if(b1 == 1) {
4723 add(m_zero, OPERATION_EQUALS);
4724 calculatesub(eo, eo, false);
4725 MERGE_APPROX_AND_PREC(mstruct)
4726 return 1;
4727 }
4728 MathStructure *mstruct2 = new MathStructure(*this);
4729 add(mstruct, OPERATION_LOGICAL_AND);
4730 LAST.calculateLogicalNot(eo);
4731 LAST.calculatesub(eo, eo, false);
4732 calculatesub(eo, eo, false);
4733 mstruct2->setLogicalNot();
4734 mstruct2->calculatesub(eo, eo, false);
4735 mstruct2->add(mstruct, OPERATION_LOGICAL_AND);
4736 mstruct2->calculatesub(eo, eo, false);
4737 add_nocopy(mstruct2, OPERATION_LOGICAL_OR);
4738 calculatesub(eo, eo, false);
4739
4740 return 1;*/
4741
4742 }
4743
4744
merge_bitwise_and(MathStructure & mstruct,const EvaluationOptions & eo,MathStructure *,size_t,size_t,bool)4745 int MathStructure::merge_bitwise_and(MathStructure &mstruct, const EvaluationOptions &eo, MathStructure*, size_t, size_t, bool) {
4746 if(mstruct.type() == STRUCT_NUMBER && m_type == STRUCT_NUMBER) {
4747 Number nr(o_number);
4748 if(nr.bitAnd(mstruct.number()) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || mstruct.number().isApproximate()) && (eo.allow_complex || !nr.isComplex() || o_number.isComplex() || mstruct.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || o_number.includesInfinity() || mstruct.number().includesInfinity())) {
4749 if(o_number == nr) {
4750 o_number = nr;
4751 numberUpdated();
4752 return 2;
4753 }
4754 o_number = nr;
4755 numberUpdated();
4756 return 1;
4757 }
4758 return -1;
4759 }
4760 switch(m_type) {
4761 case STRUCT_VECTOR: {
4762 switch(mstruct.type()) {
4763 case STRUCT_VECTOR: {
4764 if(SIZE < mstruct.size()) return 0;
4765 for(size_t i = 0; i < mstruct.size(); i++) {
4766 mstruct[i].ref();
4767 CHILD(i).add_nocopy(&mstruct[i], OPERATION_LOGICAL_AND);
4768 CHILD(i).calculatesub(eo, eo, false);
4769 }
4770 MERGE_APPROX_AND_PREC(mstruct)
4771 return 1;
4772 }
4773 default: {
4774 return -1;
4775 }
4776 }
4777 return -1;
4778 }
4779 case STRUCT_BITWISE_AND: {
4780 switch(mstruct.type()) {
4781 case STRUCT_VECTOR: {
4782 return -1;
4783 }
4784 case STRUCT_BITWISE_AND: {
4785 for(size_t i = 0; i < mstruct.size(); i++) {
4786 APPEND_REF(&mstruct[i]);
4787 }
4788 calculatesub(eo, eo, false);
4789 MERGE_APPROX_AND_PREC(mstruct)
4790 return 1;
4791 }
4792 default: {
4793 APPEND_REF(&mstruct);
4794 calculatesub(eo, eo, false);
4795 MERGE_APPROX_AND_PREC(mstruct)
4796 return 1;
4797 }
4798 }
4799 break;
4800 }
4801 default: {
4802 switch(mstruct.type()) {
4803 case STRUCT_BITWISE_AND: {
4804 return 0;
4805 }
4806 default: {}
4807 }
4808 }
4809 }
4810 return -1;
4811 }
merge_bitwise_or(MathStructure & mstruct,const EvaluationOptions & eo,MathStructure *,size_t,size_t,bool)4812 int MathStructure::merge_bitwise_or(MathStructure &mstruct, const EvaluationOptions &eo, MathStructure*, size_t, size_t, bool) {
4813 if(mstruct.type() == STRUCT_NUMBER && m_type == STRUCT_NUMBER) {
4814 Number nr(o_number);
4815 if(nr.bitOr(mstruct.number()) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || mstruct.number().isApproximate()) && (eo.allow_complex || !nr.isComplex() || o_number.isComplex() || mstruct.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || o_number.includesInfinity() || mstruct.number().includesInfinity())) {
4816 if(o_number == nr) {
4817 o_number = nr;
4818 numberUpdated();
4819 return 2;
4820 }
4821 o_number = nr;
4822 numberUpdated();
4823 return 1;
4824 }
4825 return -1;
4826 }
4827 switch(m_type) {
4828 case STRUCT_VECTOR: {
4829 switch(mstruct.type()) {
4830 case STRUCT_VECTOR: {
4831 if(SIZE < mstruct.size()) return 0;
4832 for(size_t i = 0; i < mstruct.size(); i++) {
4833 mstruct[i].ref();
4834 CHILD(i).add_nocopy(&mstruct[i], OPERATION_LOGICAL_OR);
4835 CHILD(i).calculatesub(eo, eo, false);
4836 }
4837 MERGE_APPROX_AND_PREC(mstruct)
4838 return 1;
4839 }
4840 default: {
4841 return -1;
4842 }
4843 }
4844 return -1;
4845 }
4846 case STRUCT_BITWISE_OR: {
4847 switch(mstruct.type()) {
4848 case STRUCT_VECTOR: {
4849 return -1;
4850 }
4851 case STRUCT_BITWISE_OR: {
4852 for(size_t i = 0; i < mstruct.size(); i++) {
4853 APPEND_REF(&mstruct[i]);
4854 }
4855 calculatesub(eo, eo, false);
4856 MERGE_APPROX_AND_PREC(mstruct)
4857 return 1;
4858 }
4859 default: {
4860 APPEND_REF(&mstruct);
4861 calculatesub(eo, eo, false);
4862 MERGE_APPROX_AND_PREC(mstruct)
4863 return 1;
4864 }
4865 }
4866 break;
4867 }
4868 default: {
4869 switch(mstruct.type()) {
4870 case STRUCT_BITWISE_OR: {
4871 return 0;
4872 }
4873 default: {}
4874 }
4875 }
4876 }
4877 return -1;
4878 }
merge_bitwise_xor(MathStructure & mstruct,const EvaluationOptions & eo,MathStructure *,size_t,size_t,bool)4879 int MathStructure::merge_bitwise_xor(MathStructure &mstruct, const EvaluationOptions &eo, MathStructure*, size_t, size_t, bool) {
4880 if(mstruct.type() == STRUCT_NUMBER && m_type == STRUCT_NUMBER) {
4881 Number nr(o_number);
4882 if(nr.bitXor(mstruct.number()) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || mstruct.number().isApproximate()) && (eo.allow_complex || !nr.isComplex() || o_number.isComplex() || mstruct.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || o_number.includesInfinity() || mstruct.number().includesInfinity())) {
4883 if(o_number == nr) {
4884 o_number = nr;
4885 numberUpdated();
4886 return 2;
4887 }
4888 o_number = nr;
4889 numberUpdated();
4890 return 1;
4891 }
4892 return -1;
4893 }
4894 switch(m_type) {
4895 case STRUCT_VECTOR: {
4896 switch(mstruct.type()) {
4897 case STRUCT_VECTOR: {
4898 if(SIZE < mstruct.size()) return 0;
4899 for(size_t i = 0; i < mstruct.size(); i++) {
4900 mstruct[i].ref();
4901 CHILD(i).add_nocopy(&mstruct[i], OPERATION_LOGICAL_XOR);
4902 CHILD(i).calculatesub(eo, eo, false);
4903 }
4904 MERGE_APPROX_AND_PREC(mstruct)
4905 return 1;
4906 }
4907 default: {
4908 return -1;
4909 }
4910 }
4911 return -1;
4912 }
4913 default: {}
4914 }
4915 return -1;
4916 }
4917
4918 #define MERGE_RECURSE if(recursive) {\
4919 for(size_t i = 0; i < SIZE; i++) {\
4920 if(CALCULATOR->aborted()) break;\
4921 if(!CHILD(i).isNumber()) CHILD(i).calculatesub(eo, feo, true, this, i);\
4922 }\
4923 CHILDREN_UPDATED;\
4924 }
4925
4926 #define MERGE_ALL(FUNC, TRY_LABEL) size_t i2, i3 = SIZE;\
4927 bool do_abort = false; \
4928 for(size_t i = 0; SIZE > 0 && i < SIZE - 1; i++) {\
4929 i2 = i + 1;\
4930 TRY_LABEL:\
4931 for(; i2 < i; i2++) {\
4932 if(CALCULATOR->aborted()) break;\
4933 int r = CHILD(i2).FUNC(CHILD(i), eo, this, i2, i);\
4934 if(r == 0) {\
4935 SWAP_CHILDREN(i2, i);\
4936 r = CHILD(i2).FUNC(CHILD(i), eo, this, i2, i, true);\
4937 if(r < 1) {\
4938 SWAP_CHILDREN(i2, i);\
4939 }\
4940 }\
4941 if(r >= 1) {\
4942 ERASE(i);\
4943 b = true;\
4944 i3 = i;\
4945 i = i2;\
4946 i2 = 0;\
4947 goto TRY_LABEL;\
4948 }\
4949 }\
4950 for(i2 = i + 1; i2 < SIZE; i2++) {\
4951 if(CALCULATOR->aborted()) break;\
4952 int r = CHILD(i).FUNC(CHILD(i2), eo, this, i, i2);\
4953 if(r == 0) {\
4954 SWAP_CHILDREN(i, i2);\
4955 r = CHILD(i).FUNC(CHILD(i2), eo, this, i, i2, true);\
4956 if(r < 1) {\
4957 SWAP_CHILDREN(i, i2);\
4958 } else if(r == 2) {\
4959 r = 3;\
4960 } else if(r == 3) {\
4961 r = 2;\
4962 }\
4963 }\
4964 if(r >= 1) {\
4965 ERASE(i2);\
4966 b = true;\
4967 if(r != 2) {\
4968 i2 = 0;\
4969 goto TRY_LABEL;\
4970 }\
4971 i2--;\
4972 } else if(CHILD(i).isDateTime()) {\
4973 do_abort = true;\
4974 break;\
4975 }\
4976 }\
4977 if(do_abort) break;\
4978 if(i3 < SIZE) {\
4979 if(i3 == SIZE - 1) break;\
4980 i = i3;\
4981 i3 = SIZE;\
4982 i2 = i + 1;\
4983 goto TRY_LABEL;\
4984 }\
4985 }
4986
4987 #define MERGE_ALL2 if(SIZE == 1) {\
4988 setToChild(1, false, mparent, index_this + 1);\
4989 } else if(SIZE == 0) {\
4990 clear(true);\
4991 } else {\
4992 evalSort();\
4993 }
4994
fix_intervals(MathStructure & mstruct,const EvaluationOptions & eo,bool * failed,long int min_precision,bool function_middle)4995 bool fix_intervals(MathStructure &mstruct, const EvaluationOptions &eo, bool *failed, long int min_precision, bool function_middle) {
4996 if(mstruct.type() == STRUCT_NUMBER) {
4997 if(eo.interval_calculation != INTERVAL_CALCULATION_NONE) {
4998 if(!mstruct.number().isInterval(false) && mstruct.number().precision() >= 0 && (CALCULATOR->usesIntervalArithmetic() || mstruct.number().precision() <= PRECISION + 10)) {
4999 mstruct.number().precisionToInterval();
5000 mstruct.setPrecision(-1);
5001 mstruct.numberUpdated();
5002 return true;
5003 }
5004 } else if(mstruct.number().isInterval(false)) {
5005 if(!mstruct.number().intervalToPrecision(min_precision)) {
5006 if(failed) *failed = true;
5007 return false;
5008 }
5009 mstruct.numberUpdated();
5010 return true;
5011 }
5012 } else if(mstruct.type() == STRUCT_FUNCTION && (mstruct.function()->id() == FUNCTION_ID_INTERVAL || mstruct.function()->id() == FUNCTION_ID_UNCERTAINTY)) {
5013 if(eo.interval_calculation == INTERVAL_CALCULATION_NONE) {
5014 bool b = mstruct.calculateFunctions(eo, false);
5015 if(b) {
5016 fix_intervals(mstruct, eo, failed, function_middle);
5017 return true;
5018 } else if(function_middle && mstruct.type() == STRUCT_FUNCTION && mstruct.function()->id() == FUNCTION_ID_INTERVAL && mstruct.size() == 2) {
5019 mstruct.setType(STRUCT_ADDITION);
5020 mstruct.divide(nr_two);
5021 return true;
5022 } else if(function_middle && mstruct.type() == STRUCT_FUNCTION && mstruct.function()->id() == FUNCTION_ID_UNCERTAINTY && mstruct.size() >= 1) {
5023 mstruct.setToChild(1, true);
5024 return true;
5025 }
5026 }
5027 } else {
5028 bool b = false;
5029 for(size_t i = 0; i < mstruct.size(); i++) {
5030 if(fix_intervals(mstruct[i], eo, failed, function_middle)) {
5031 mstruct.childUpdated(i + 1);
5032 b = true;
5033 }
5034 }
5035 return b;
5036 }
5037 return false;
5038 }
5039
5040 bool contains_zero_unit(const MathStructure &mstruct);
contains_zero_unit(const MathStructure & mstruct)5041 bool contains_zero_unit(const MathStructure &mstruct) {
5042 if(mstruct.isMultiplication() && mstruct.size() > 1 && mstruct[0].isZero()) {
5043 bool b = true;
5044 for(size_t i = 1; i < mstruct.size(); i++) {
5045 if(!mstruct[i].isUnit_exp()) {
5046 b = false;
5047 break;
5048 }
5049 }
5050 if(b) return true;
5051 }
5052 for(size_t i = 0; i < mstruct.size(); i++) {
5053 if(contains_zero_unit(mstruct[i])) return true;
5054 }
5055 return false;
5056 }
5057
test_var_int(const MathStructure & mstruct,bool * v=NULL)5058 bool test_var_int(const MathStructure &mstruct, bool *v = NULL) {
5059 if(mstruct.isVariable() && (mstruct.variable()->id() == VARIABLE_ID_E || mstruct.variable()->id() == VARIABLE_ID_PI)) {
5060 if(!v) return true;
5061 if(*v) return false;
5062 else *v = true;
5063 return true;
5064 }
5065 if(mstruct.isNumber() && mstruct.number().isReal()) {
5066 if(!v) {
5067 if(mstruct.number().isInterval()) {
5068 Number nr_int(mstruct.number());
5069 nr_int.round();
5070 return mstruct.number() < nr_int || mstruct.number() > nr_int;
5071 }
5072 if(mstruct.isApproximate()) {
5073 Number nr_f = mstruct.number();
5074 nr_f.floor();
5075 Number nr_c(nr_f);
5076 nr_c++;
5077 return COMPARISON_IS_NOT_EQUAL(mstruct.number().compareApproximately(nr_f)) && COMPARISON_IS_NOT_EQUAL(mstruct.number().compareApproximately(nr_c));
5078 }
5079 return !mstruct.number().isInterval() && !mstruct.number().isInteger();
5080 }
5081 if(mstruct.isApproximate()) return false;
5082 return mstruct.number().isRational();
5083 }
5084 if(mstruct.isMultiplication() || mstruct.isAddition() || (mstruct.isPower() && mstruct[1].isInteger())) {
5085 bool v2 = false;
5086 if(!v) v = &v2;
5087 for(size_t i = 0; i < mstruct.size(); i++) {
5088 if(!test_var_int(mstruct[i], v)) return false;
5089 }
5090 if(*v) return true;
5091 }
5092 return false;
5093 }
5094
test_non_integer(const MathStructure & mstruct,const EvaluationOptions &)5095 bool test_non_integer(const MathStructure &mstruct, const EvaluationOptions&) {
5096 if(test_var_int(mstruct)) return true;
5097 if(!mstruct.isApproximate()) {
5098 if((mstruct.isMultiplication() || mstruct.isAddition()) && mstruct.size() >= 2 && mstruct[0].isNumber() && mstruct[0].number().isReal() && !mstruct[0].number().isInterval() && !mstruct[0].number().isInteger()) {
5099 for(size_t i = 1; i < mstruct.size(); i++) {
5100 if(!mstruct[i].representsInteger()) return false;
5101 }
5102 return true;
5103 }
5104 }
5105 return false;
5106 }
factorizeUnits()5107 bool MathStructure::factorizeUnits() {
5108 switch(m_type) {
5109 case STRUCT_ADDITION: {
5110 if(containsType(STRUCT_DATETIME, false, true, false) > 0) return false;
5111 bool b = false;
5112 MathStructure mstruct_units(*this);
5113 MathStructure mstruct_new(*this);
5114 for(size_t i = 0; i < mstruct_units.size(); i++) {
5115 if(CALCULATOR->aborted()) break;
5116 if(mstruct_units[i].isMultiplication()) {
5117 for(size_t i2 = 0; i2 < mstruct_units[i].size();) {
5118 if(CALCULATOR->aborted()) break;
5119 if(!mstruct_units[i][i2].isUnit_exp()) {
5120 mstruct_units[i].delChild(i2 + 1);
5121 } else {
5122 i2++;
5123 }
5124 }
5125 if(mstruct_units[i].size() == 0) mstruct_units[i].setUndefined();
5126 else if(mstruct_units[i].size() == 1) mstruct_units[i].setToChild(1);
5127 for(size_t i2 = 0; i2 < mstruct_new[i].size();) {
5128 if(CALCULATOR->aborted()) break;
5129 if(mstruct_new[i][i2].isUnit_exp()) {
5130 mstruct_new[i].delChild(i2 + 1);
5131 } else {
5132 i2++;
5133 }
5134 }
5135 if(mstruct_new[i].size() == 0) mstruct_new[i].set(1, 1, 0);
5136 else if(mstruct_new[i].size() == 1) mstruct_new[i].setToChild(1);
5137 } else if(mstruct_units[i].isUnit_exp()) {
5138 mstruct_new[i].set(1, 1, 0);
5139 } else {
5140 mstruct_units[i].setUndefined();
5141 }
5142 }
5143 for(size_t i = 0; i < mstruct_units.size(); i++) {
5144 if(CALCULATOR->aborted()) break;
5145 if(!mstruct_units[i].isUndefined()) {
5146 for(size_t i2 = i + 1; i2 < mstruct_units.size();) {
5147 if(mstruct_units[i2] == mstruct_units[i]) {
5148 mstruct_new[i].add(mstruct_new[i2], true);
5149 mstruct_new.delChild(i2 + 1);
5150 mstruct_units.delChild(i2 + 1);
5151 b = true;
5152 } else {
5153 i2++;
5154 }
5155 }
5156 if(mstruct_new[i].isOne()) mstruct_new[i].set(mstruct_units[i]);
5157 else mstruct_new[i].multiply(mstruct_units[i], true);
5158 }
5159 }
5160 if(b) {
5161 if(mstruct_new.size() == 1) set(mstruct_new[0], true);
5162 else set(mstruct_new, true);
5163 return true;
5164 }
5165 }
5166 default: {
5167 bool b = false;
5168 for(size_t i = 0; i < SIZE; i++) {
5169 if(CALCULATOR->aborted()) break;
5170 if(CHILD(i).factorizeUnits()) {
5171 CHILD_UPDATED(i);
5172 b = true;
5173 }
5174 }
5175 return b;
5176 }
5177 }
5178 }
contains_temp_unit(const MathStructure & m,bool top=true)5179 int contains_temp_unit(const MathStructure &m, bool top = true) {
5180 if(m.isUnit() && (m.unit() == CALCULATOR->getUnitById(UNIT_ID_KELVIN) || m.unit()->containsRelativeTo(CALCULATOR->getUnitById(UNIT_ID_KELVIN)))) {
5181 return 1;
5182 } else if(m.isPower() && m[0].isUnit() && (m[0].unit() == CALCULATOR->getUnitById(UNIT_ID_KELVIN) || m[0].unit()->containsRelativeTo(CALCULATOR->getUnitById(UNIT_ID_KELVIN)))) {
5183 return 2;
5184 } else if(top && m.isMultiplication()) {
5185 bool b_unit = false;
5186 int i_ret = 0;
5187 for(size_t i = 0; i < m.size(); i++) {
5188 if(!i_ret) {
5189 i_ret = contains_temp_unit(m[i], false);
5190 if(i_ret == 2 || (i_ret && b_unit)) return 2;
5191 if(!i_ret && !b_unit && m[i].containsType(STRUCT_UNIT, false, false, false)) b_unit = true;
5192 } else if(!b_unit && m[i].containsType(STRUCT_UNIT, false, false, false)) {
5193 return 2;
5194 }
5195 }
5196 return i_ret;
5197 }
5198 return 0;
5199 }
5200
calculatesub(const EvaluationOptions & eo,const EvaluationOptions & feo,bool recursive,MathStructure * mparent,size_t index_this)5201 bool MathStructure::calculatesub(const EvaluationOptions &eo, const EvaluationOptions &feo, bool recursive, MathStructure *mparent, size_t index_this) {
5202
5203 // do not modify MathStructure marked as protected
5204 if(b_protected) return false;
5205
5206 bool b = false;
5207
5208 // the normal process here is the first calculate all children (if recursive) and try merging every child with every other child
5209
5210 switch(m_type) {
5211 case STRUCT_VARIABLE: {
5212 if(eo.calculate_variables && o_variable->isKnown()) {
5213 // replace variable with value of calculation is approximate or variable is exact (variable is approximate if marked as approximate or value contains interval)
5214 if((eo.approximation == APPROXIMATION_APPROXIMATE || (!o_variable->isApproximate() && !((KnownVariable*) o_variable)->get().containsInterval(true, false, false, 0, true))) && !((KnownVariable*) o_variable)->get().isAborted()) {
5215 set(((KnownVariable*) o_variable)->get());
5216 unformat(eo);
5217 if(eo.calculate_functions) {
5218 // calculate any functions in the variable value
5219 calculateFunctions(feo);
5220 }
5221 // replace precision with interval and vice versa depending on interval calculation mode (foremost relevant for INTERVAL_CALCULATION_NONE)
5222 fix_intervals(*this, feo, NULL, PRECISION);
5223 b = true;
5224 calculatesub(eo, feo, true, mparent, index_this);
5225 }
5226 }
5227 break;
5228 }
5229 case STRUCT_POWER: {
5230 if(recursive) {
5231 CHILD(0).calculatesub(eo, feo, true, this, 0);
5232 CHILD(1).calculatesub(eo, feo, true, this, 1);
5233 CHILDREN_UPDATED;
5234 }
5235 if(eo.sync_units && CHILD(0).isUnit() && CALCULATOR->getTemperatureCalculationMode() == TEMPERATURE_CALCULATION_RELATIVE && !CHILD(1).isOne()) {
5236 if(CHILD(0).unit() == CALCULATOR->getUnitById(UNIT_ID_CELSIUS) && CALCULATOR->getUnitById(UNIT_ID_KELVIN)) CHILD(0).setUnit(CALCULATOR->getUnitById(UNIT_ID_KELVIN));
5237 else if(CHILD(0).unit() == CALCULATOR->getUnitById(UNIT_ID_FAHRENHEIT) && CALCULATOR->getUnitById(UNIT_ID_RANKINE)) CHILD(0).setUnit(CALCULATOR->getUnitById(UNIT_ID_RANKINE));
5238 }
5239 if(CHILD(0).merge_power(CHILD(1), eo) >= 1) {
5240 b = true;
5241 setToChild(1, false, mparent, index_this + 1);
5242 }
5243 break;
5244 }
5245 case STRUCT_ADDITION: {
5246 MERGE_RECURSE
5247 bool found_nonlinear_relations = false;
5248 // convert units with nonlinear relation (to units in other terms) first
5249 if(eo.sync_units && (syncUnits(false, &found_nonlinear_relations, true, feo) || (found_nonlinear_relations && eo.sync_nonlinear_unit_relations))) {
5250 if(found_nonlinear_relations && eo.sync_nonlinear_unit_relations) {
5251 EvaluationOptions eo2 = eo;
5252 eo2.expand = -3;
5253 eo2.combine_divisions = false;
5254 int temp_unit_found = 0;
5255 for(size_t i = 0; i < SIZE; i++) {
5256 CHILD(i).calculatesub(eo2, feo, true, this, i);
5257 CHILD(i).factorizeUnits();
5258 if(temp_unit_found == 1) temp_unit_found++;
5259 if(!temp_unit_found && CALCULATOR->getTemperatureCalculationMode() == TEMPERATURE_CALCULATION_RELATIVE) {
5260 temp_unit_found = contains_temp_unit(CHILD(i));
5261 }
5262 if(temp_unit_found > 1) {
5263 if(CALCULATOR->getUnitById(UNIT_ID_FAHRENHEIT) && CALCULATOR->getUnitById(UNIT_ID_RANKINE)) CHILD(i).replace(CALCULATOR->getUnitById(UNIT_ID_FAHRENHEIT), CALCULATOR->getUnitById(UNIT_ID_RANKINE));
5264 if(CALCULATOR->getUnitById(UNIT_ID_CELSIUS) && CALCULATOR->getUnitById(UNIT_ID_KELVIN)) CHILD(i).replace(CALCULATOR->getUnitById(UNIT_ID_CELSIUS), CALCULATOR->getUnitById(UNIT_ID_KELVIN));
5265 }
5266 }
5267 CHILDREN_UPDATED;
5268 if(temp_unit_found) CALCULATOR->beginTemporaryStopMessages();
5269 syncUnits(true, NULL, true, feo);
5270 if(temp_unit_found) CALCULATOR->endTemporaryStopMessages();
5271 }
5272 unformat(eo);
5273 MERGE_RECURSE
5274 }
5275 MERGE_ALL(merge_addition, try_add)
5276 MERGE_ALL2
5277 break;
5278 }
5279 case STRUCT_MULTIPLICATION: {
5280
5281 MERGE_RECURSE
5282
5283 if(eo.sync_units && CALCULATOR->getTemperatureCalculationMode() == TEMPERATURE_CALCULATION_RELATIVE) {
5284 int temp_unit_found = 0;
5285 for(size_t i = 0; i < SIZE && temp_unit_found < 2; i++) {
5286 if(!temp_unit_found && CALCULATOR->getTemperatureCalculationMode() == TEMPERATURE_CALCULATION_RELATIVE) {
5287 temp_unit_found = contains_temp_unit(CHILD(i), false);
5288 if(temp_unit_found < 0) temp_unit_found = 2;
5289 } else if(CHILD(i).isUnit_exp()) {
5290 if(temp_unit_found) temp_unit_found = 2;
5291 else temp_unit_found = -1;
5292 }
5293 }
5294 if(temp_unit_found > 1) {
5295 replace(CALCULATOR->getUnitById(UNIT_ID_FAHRENHEIT), CALCULATOR->getUnitById(UNIT_ID_RANKINE));
5296 replace(CALCULATOR->getUnitById(UNIT_ID_CELSIUS), CALCULATOR->getUnitById(UNIT_ID_KELVIN));
5297 }
5298 if(temp_unit_found) CALCULATOR->beginTemporaryStopMessages();
5299 syncUnits(true, NULL, true, feo);
5300 if(temp_unit_found) CALCULATOR->endTemporaryStopMessages();
5301 }
5302 if(eo.sync_units && syncUnits(eo.sync_nonlinear_unit_relations, NULL, true, feo)) {
5303 unformat(eo);
5304 MERGE_RECURSE
5305 }
5306
5307 if(representsNonMatrix()) {
5308
5309 if(SIZE > 2) {
5310 int nonintervals = 0, had_interval = false;
5311 for(size_t i = 0; i < SIZE; i++) {
5312 if(CHILD(i).isNumber()) {
5313 if(CHILD(i).number().isInterval(false)) {
5314 had_interval = true;
5315 if(nonintervals >= 2) break;
5316 } else if(nonintervals < 2) {
5317 nonintervals++;
5318 if(nonintervals == 2 && had_interval) break;
5319 }
5320 }
5321 }
5322 if(had_interval && nonintervals >= 2) evalSort(false);
5323 }
5324
5325 MERGE_ALL(merge_multiplication, try_multiply)
5326
5327 } else {
5328 // matrix factors are not reorderable
5329 size_t i2, i3 = SIZE;
5330 for(size_t i = 0; i < SIZE - 1; i++) {
5331 i2 = i + 1;
5332 try_multiply_matrix:
5333 bool b_matrix = !CHILD(i).representsNonMatrix();
5334 if(i2 < i) {
5335 for(; ; i2--) {
5336 int r = CHILD(i2).merge_multiplication(CHILD(i), eo, this, i2, i);
5337 if(r == 0) {
5338 SWAP_CHILDREN(i2, i);
5339 r = CHILD(i2).merge_multiplication(CHILD(i), eo, this, i2, i, true);
5340 if(r < 1) {
5341 SWAP_CHILDREN(i2, i);
5342 }
5343 }
5344 if(r >= 1) {
5345 ERASE(i);
5346 b = true;
5347 i3 = i;
5348 i = i2;
5349 i2 = 0;
5350 goto try_multiply_matrix;
5351 }
5352 if(i2 == 0) break;
5353 if(b_matrix && !CHILD(i2).representsNonMatrix()) break;
5354 }
5355 }
5356 bool had_matrix = false;
5357 for(i2 = i + 1; i2 < SIZE; i2++) {
5358 if(had_matrix && !CHILD(i2).representsNonMatrix()) continue;
5359 int r = CHILD(i).merge_multiplication(CHILD(i2), eo, this, i, i2);
5360 if(r == 0) {
5361 SWAP_CHILDREN(i, i2);
5362 r = CHILD(i).merge_multiplication(CHILD(i2), eo, this, i, i2, true);
5363 if(r < 1) {
5364 SWAP_CHILDREN(i, i2);
5365 } else if(r == 2) {
5366 r = 3;
5367 } else if(r == 3) {
5368 r = 2;
5369 }
5370 }
5371 if(r >= 1) {
5372 ERASE(i2);
5373 b = true;
5374 if(r != 2) {
5375 i2 = 0;
5376 goto try_multiply_matrix;
5377 }
5378 i2--;
5379 }
5380 if(i == SIZE - 1) break;
5381 if(b_matrix && !CHILD(i2).representsNonMatrix()) had_matrix = true;
5382 }
5383 if(i3 < SIZE) {
5384 if(i3 == SIZE - 1) break;
5385 i = i3;
5386 i3 = SIZE;
5387 i2 = i + 1;
5388 goto try_multiply_matrix;
5389 }
5390 }
5391 }
5392
5393 MERGE_ALL2
5394
5395 break;
5396 }
5397 case STRUCT_BITWISE_AND: {
5398 MERGE_RECURSE
5399 MERGE_ALL(merge_bitwise_and, try_bitand)
5400 MERGE_ALL2
5401 break;
5402 }
5403 case STRUCT_BITWISE_OR: {
5404 MERGE_RECURSE
5405 MERGE_ALL(merge_bitwise_or, try_bitor)
5406 MERGE_ALL2
5407 break;
5408 }
5409 case STRUCT_BITWISE_XOR: {
5410 MERGE_RECURSE
5411 MERGE_ALL(merge_bitwise_xor, try_bitxor)
5412 MERGE_ALL2
5413 break;
5414 }
5415 case STRUCT_BITWISE_NOT: {
5416 if(recursive) {
5417 CHILD(0).calculatesub(eo, feo, true, this, 0);
5418 CHILDREN_UPDATED;
5419 }
5420 switch(CHILD(0).type()) {
5421 case STRUCT_NUMBER: {
5422 Number nr(CHILD(0).number());
5423 if(nr.bitNot() && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || CHILD(0).number().isApproximate()) && (eo.allow_complex || !nr.isComplex() || CHILD(0).number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || CHILD(0).number().includesInfinity())) {
5424 set(nr, true);
5425 }
5426 break;
5427 }
5428 case STRUCT_VECTOR: {
5429 SET_CHILD_MAP(0);
5430 for(size_t i = 0; i < SIZE; i++) {
5431 CHILD(i).setLogicalNot();
5432 }
5433 break;
5434 }
5435 case STRUCT_BITWISE_NOT: {
5436 //~(~a)=a
5437 setToChild(1);
5438 setToChild(1);
5439 break;
5440 }
5441 default: {}
5442 }
5443 break;
5444 }
5445 case STRUCT_LOGICAL_AND: {
5446 if(recursive) {
5447 for(size_t i = 0; i < SIZE; i++) {
5448 CHILD(i).calculatesub(eo, feo, true, this, i);
5449 CHILD_UPDATED(i)
5450 if(CHILD(i).isZero()) {
5451 clear(true);
5452 b = true;
5453 break;
5454 }
5455 }
5456 if(b) break;
5457 }
5458 MERGE_ALL(merge_logical_and, try_logand)
5459 if(SIZE == 1) {
5460 if(CHILD(0).representsBoolean() || (mparent && !mparent->isMultiplication() && mparent->representsBoolean())) {
5461 setToChild(1, false, mparent, index_this + 1);
5462 } else if(CHILD(0).representsNonZero()) {
5463 set(1, 1, 0, true);
5464 } else if(CHILD(0).isZero()) {
5465 clear(true);
5466 } else {
5467 APPEND(m_zero);
5468 m_type = STRUCT_COMPARISON;
5469 ct_comp = COMPARISON_NOT_EQUALS;
5470 }
5471 } else if(SIZE == 0) {
5472 clear(true);
5473 } else {
5474 evalSort();
5475 }
5476 break;
5477 }
5478 case STRUCT_LOGICAL_OR: {
5479 bool isResistance = false;
5480 // calculate resistance || resistance as parallel resistor (?)
5481 if(recursive) {
5482 for(size_t i = 0; i < SIZE; i++) {
5483 CHILD(i).calculatesub(eo, feo, true, this, i);
5484 CHILD_UPDATED(i)
5485 if(CHILD(i).representsNonZero()) {
5486 set(1, 1, 0, true);
5487 b = true;
5488 break;
5489 }
5490 }
5491 if(b) break;
5492 }
5493 switch(CHILD(0).type()) {
5494 case STRUCT_MULTIPLICATION: {
5495 if(CHILD(0)[1] != 0 && CHILD(0)[1].unit() && CHILD(0)[1].unit()->name().find("ohm") != string::npos) {
5496 isResistance = true;
5497 }
5498 break;
5499 }
5500 case STRUCT_UNIT: {
5501 if(CHILD(0).unit() && CHILD(0).unit()->name().find("ohm") != string::npos) {
5502 isResistance = true;
5503 }
5504 break;
5505 }
5506 default: {}
5507 }
5508 if(isResistance) {
5509 MathStructure mstruct;
5510 for (size_t i = 0; i < SIZE; i++) {
5511 MathStructure mtemp(CHILD(i));
5512 mtemp.inverse();
5513 mstruct += mtemp;
5514 }
5515 mstruct.inverse();
5516 clear();
5517 set(mstruct);
5518 break;
5519 }
5520 MERGE_ALL(merge_logical_or, try_logor)
5521 if(SIZE == 1) {
5522 if(CHILD(0).representsBoolean() || (mparent && !mparent->isMultiplication() && mparent->representsBoolean())) {
5523 setToChild(1, false, mparent, index_this + 1);
5524 } else if(CHILD(0).representsNonZero()) {
5525 set(1, 1, 0, true);
5526 } else if(CHILD(0).isZero()) {
5527 clear(true);
5528 } else {
5529 APPEND(m_zero);
5530 m_type = STRUCT_COMPARISON;
5531 ct_comp = COMPARISON_NOT_EQUALS;
5532 }
5533 } else if(SIZE == 0) {
5534 clear(true);
5535 } else {
5536 evalSort();
5537 }
5538 break;
5539 }
5540 case STRUCT_LOGICAL_XOR: {
5541 if(recursive) {
5542 CHILD(0).calculatesub(eo, feo, true, this, 0);
5543 CHILD(1).calculatesub(eo, feo, true, this, 1);
5544 CHILDREN_UPDATED;
5545 }
5546 if(CHILD(0).merge_logical_xor(CHILD(1), eo) >= 1) {
5547 b = true;
5548 setToChild(1, false, mparent, index_this + 1);
5549 }
5550 break;
5551 }
5552 case STRUCT_LOGICAL_NOT: {
5553 if(recursive) {
5554 CHILD(0).calculatesub(eo, feo, true, this, 0);
5555 CHILDREN_UPDATED;
5556 }
5557 if(CHILD(0).representsNonZero()) {
5558 clear(true);
5559 b = true;
5560 } else if(CHILD(0).isZero()) {
5561 set(1, 1, 0, true);
5562 b = true;
5563 } else if(CHILD(0).isLogicalNot()) {
5564 // !(!a)=a
5565 setToChild(1);
5566 setToChild(1);
5567 if(!representsBoolean() || (mparent && !mparent->isMultiplication() && mparent->representsBoolean())) {
5568 add(m_zero, OPERATION_NOT_EQUALS);
5569 calculatesub(eo, feo, false);
5570 }
5571 b = true;
5572 }
5573 break;
5574 }
5575 case STRUCT_COMPARISON: {
5576 EvaluationOptions eo2 = eo;
5577 if(eo2.assume_denominators_nonzero == 1) eo2.assume_denominators_nonzero = false;
5578 if(recursive) {
5579 CHILD(0).calculatesub(eo2, feo, true, this, 0);
5580 CHILD(1).calculatesub(eo2, feo, true, this, 1);
5581 CHILDREN_UPDATED;
5582 }
5583 if(eo.sync_units && syncUnits(eo.sync_nonlinear_unit_relations, NULL, true, feo)) {
5584 unformat(eo);
5585 if(recursive) {
5586 CHILD(0).calculatesub(eo2, feo, true, this, 0);
5587 CHILD(1).calculatesub(eo2, feo, true, this, 1);
5588 CHILDREN_UPDATED;
5589 }
5590 }
5591 if(CHILD(0).isAddition() || CHILD(1).isAddition()) {
5592 size_t i2 = 0;
5593 for(size_t i = 0; !CHILD(0).isAddition() || i < CHILD(0).size(); i++) {
5594 if(CHILD(1).isAddition()) {
5595 for(; i2 < CHILD(1).size(); i2++) {
5596 if(CHILD(0).isAddition() && CHILD(0)[i] == CHILD(1)[i2]) {
5597 CHILD(0).delChild(i + 1);
5598 CHILD(1).delChild(i2 + 1);
5599 break;
5600 } else if(!CHILD(0).isAddition() && CHILD(0) == CHILD(1)[i2]) {
5601 CHILD(0).clear(true);
5602 CHILD(1).delChild(i2 + 1);
5603 break;
5604 }
5605 }
5606 } else if(CHILD(0)[i] == CHILD(1)) {
5607 CHILD(1).clear(true);
5608 CHILD(0).delChild(i + 1);
5609 break;
5610 }
5611 if(!CHILD(0).isAddition()) break;
5612 }
5613 if(CHILD(0).isAddition()) {
5614 if(CHILD(0).size() == 1) CHILD(0).setToChild(1, true);
5615 else if(CHILD(0).size() == 0) CHILD(0).clear(true);
5616 }
5617 if(CHILD(1).isAddition()) {
5618 if(CHILD(1).size() == 1) CHILD(1).setToChild(1, true);
5619 else if(CHILD(1).size() == 0) CHILD(1).clear(true);
5620 }
5621 }
5622 if(CHILD(0).isMultiplication() && CHILD(1).isMultiplication()) {
5623 size_t i1 = 0, i2 = 0;
5624 if(CHILD(0)[0].isNumber()) i1++;
5625 if(CHILD(1)[0].isNumber()) i2++;
5626 while(i1 < CHILD(0).size() && i2 < CHILD(1).size()) {
5627 if(CHILD(0)[i1] == CHILD(1)[i2] && CHILD(0)[i1].representsPositive(true)) {
5628 CHILD(0).delChild(i1 + 1);
5629 CHILD(1).delChild(i2 + 1);
5630 } else {
5631 break;
5632 }
5633 }
5634 if(CHILD(0).size() == 1) CHILD(0).setToChild(1, true);
5635 else if(CHILD(0).size() == 0) CHILD(0).set(1, 1, 0, true);
5636 if(CHILD(1).size() == 1) CHILD(1).setToChild(1, true);
5637 else if(CHILD(1).size() == 0) CHILD(1).set(1, 1, 0, true);
5638 }
5639 if(((CHILD(0).isNumber() || (CHILD(0).isVariable() && !CHILD(0).variable()->isKnown() && ((UnknownVariable*) CHILD(0).variable())->interval().isNumber())) && (CHILD(1).isNumber() || ((CHILD(1).isVariable() && !CHILD(1).variable()->isKnown() && ((UnknownVariable*) CHILD(1).variable())->interval().isNumber())))) || (CHILD(0).isDateTime() && CHILD(1).isDateTime())) {
5640 ComparisonResult cr;
5641 if(CHILD(0).isNumber()) {
5642 if(CHILD(1).isNumber()) cr = CHILD(1).number().compareApproximately(CHILD(0).number());
5643 else cr = ((UnknownVariable*) CHILD(1).variable())->interval().number().compareApproximately(CHILD(0).number());
5644 } else if(CHILD(1).isNumber()) {
5645 cr = CHILD(1).number().compareApproximately(((UnknownVariable*) CHILD(0).variable())->interval().number());
5646 } else if(CHILD(1).isVariable()) {
5647 cr = ((UnknownVariable*) CHILD(1).variable())->interval().number().compareApproximately(((UnknownVariable*) CHILD(0).variable())->interval().number());
5648 } else {
5649 cr = CHILD(1).compare(CHILD(0));
5650 }
5651 if(cr >= COMPARISON_RESULT_UNKNOWN) {
5652 break;
5653 }
5654 switch(ct_comp) {
5655 case COMPARISON_EQUALS: {
5656 if(cr == COMPARISON_RESULT_EQUAL) {
5657 set(1, 1, 0, true);
5658 b = true;
5659 } else if(COMPARISON_IS_NOT_EQUAL(cr)) {
5660 clear(true);
5661 b = true;
5662 }
5663 break;
5664 }
5665 case COMPARISON_NOT_EQUALS: {
5666 if(cr == COMPARISON_RESULT_EQUAL) {
5667 clear(true);
5668 b = true;
5669 } else if(COMPARISON_IS_NOT_EQUAL(cr)) {
5670 set(1, 1, 0, true);
5671 b = true;
5672 }
5673 break;
5674 }
5675 case COMPARISON_LESS: {
5676 if(cr == COMPARISON_RESULT_LESS) {
5677 set(1, 1, 0, true);
5678 b = true;
5679 } else if(cr != COMPARISON_RESULT_EQUAL_OR_LESS && cr != COMPARISON_RESULT_NOT_EQUAL) {
5680 clear(true);
5681 b = true;
5682 }
5683 break;
5684 }
5685 case COMPARISON_EQUALS_LESS: {
5686 if(COMPARISON_IS_EQUAL_OR_LESS(cr)) {
5687 set(1, 1, 0, true);
5688 b = true;
5689 } else if(cr != COMPARISON_RESULT_EQUAL_OR_GREATER && cr != COMPARISON_RESULT_NOT_EQUAL) {
5690 clear(true);
5691 b = true;
5692 }
5693 break;
5694 }
5695 case COMPARISON_GREATER: {
5696 if(cr == COMPARISON_RESULT_GREATER) {
5697 set(1, 1, 0, true);
5698 b = true;
5699 } else if(cr != COMPARISON_RESULT_EQUAL_OR_GREATER && cr != COMPARISON_RESULT_NOT_EQUAL) {
5700 clear(true);
5701 b = true;
5702 }
5703 break;
5704 }
5705 case COMPARISON_EQUALS_GREATER: {
5706 if(COMPARISON_IS_EQUAL_OR_GREATER(cr)) {
5707 set(1, 1, 0, true);
5708 b = true;
5709 } else if(cr != COMPARISON_RESULT_EQUAL_OR_LESS && cr != COMPARISON_RESULT_NOT_EQUAL) {
5710 clear(true);
5711 b = true;
5712 }
5713 break;
5714 }
5715 }
5716 break;
5717 }
5718 if(!eo.test_comparisons) {
5719 break;
5720 }
5721
5722 if(eo2.keep_zero_units && contains_zero_unit(*this)) {
5723 eo2.keep_zero_units = false;
5724 MathStructure mtest(*this);
5725 CALCULATOR->beginTemporaryStopMessages();
5726 mtest.calculatesub(eo2, feo, true);
5727 if(mtest.isNumber()) {
5728 CALCULATOR->endTemporaryStopMessages(true);
5729 set(mtest);
5730 b = true;
5731 break;
5732 }
5733 CALCULATOR->endTemporaryStopMessages();
5734 }
5735 if((CHILD(0).representsUndefined() && !CHILD(1).representsUndefined(true, true, true)) || (CHILD(1).representsUndefined() && !CHILD(0).representsUndefined(true, true, true))) {
5736 if(ct_comp == COMPARISON_EQUALS) {
5737 clear(true);
5738 b = true;
5739 break;
5740 } else if(ct_comp == COMPARISON_NOT_EQUALS) {
5741 set(1, 1, 0, true);
5742 b = true;
5743 break;
5744 }
5745 }
5746 if((ct_comp == COMPARISON_EQUALS_LESS || ct_comp == COMPARISON_GREATER) && CHILD(1).isZero()) {
5747 if(CHILD(0).isLogicalNot() || CHILD(0).isLogicalAnd() || CHILD(0).isLogicalOr() || CHILD(0).isLogicalXor() || CHILD(0).isComparison()) {
5748 if(ct_comp == COMPARISON_EQUALS_LESS) {
5749 ERASE(1);
5750 m_type = STRUCT_LOGICAL_NOT;
5751 calculatesub(eo, feo, false, mparent, index_this);
5752 } else {
5753 setToChild(1, false, mparent, index_this + 1);
5754 }
5755 b = true;
5756 }
5757 } else if((ct_comp == COMPARISON_EQUALS_GREATER || ct_comp == COMPARISON_LESS) && CHILD(0).isZero()) {
5758 if(CHILD(1).isLogicalNot() || CHILD(1).isLogicalAnd() || CHILD(1).isLogicalOr() || CHILD(1).isLogicalXor() || CHILD(1).isComparison()) {
5759 if(ct_comp == COMPARISON_EQUALS_GREATER) {
5760 ERASE(0);
5761 m_type = STRUCT_LOGICAL_NOT;
5762 calculatesub(eo, feo, false, mparent, index_this);
5763 } else {
5764 setToChild(2, false, mparent, index_this + 1);
5765 }
5766 b = true;
5767 }
5768 }
5769 if(ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) {
5770 if((CHILD(0).representsReal(true) && CHILD(1).representsComplex(true)) || (CHILD(1).representsReal(true) && CHILD(0).representsComplex(true))) {
5771 if(ct_comp == COMPARISON_EQUALS) {
5772 clear(true);
5773 } else {
5774 set(1, 1, 0, true);
5775 }
5776 b = true;
5777 } else if((CHILD(0).representsZero(true) && CHILD(1).representsZero(true))) {
5778 if(ct_comp != COMPARISON_EQUALS) {
5779 clear(true);
5780 } else {
5781 set(1, 1, 0, true);
5782 }
5783 b = true;
5784 } else if(CHILD(0).isVariable() && !CHILD(0).variable()->isKnown() && CHILD(0).representsInteger() && test_non_integer(CHILD(1), eo)) {
5785 if(ct_comp == COMPARISON_EQUALS) clear(true);
5786 else set(1, 1, 0, true);
5787 b = true;
5788 }
5789 }
5790 if(b) break;
5791 if(CHILD(1).isNumber() && CHILD(0).isVariable() && !CHILD(0).variable()->isKnown()) {
5792 Assumptions *ass = ((UnknownVariable*) CHILD(0).variable())->assumptions();
5793 if(ass && ass->min()) {
5794 bool b_inc = ass->includeEqualsMin();
5795 switch(ct_comp) {
5796 case COMPARISON_EQUALS: {
5797 if((b_inc && CHILD(1).number() < *ass->min()) || (!b_inc && CHILD(1).number() <= *ass->min())) {clear(true); b = true;}
5798 break;
5799 }
5800 case COMPARISON_NOT_EQUALS: {
5801 if((b_inc && CHILD(1).number() < *ass->min()) || (!b_inc && CHILD(1).number() <= *ass->min())) {set(1, 1, 0, true); b = true;}
5802 break;
5803 }
5804 case COMPARISON_LESS: {
5805 if(CHILD(1).number() <= *ass->min()) {clear(true); b = true;}
5806
5807 break;
5808 }
5809 case COMPARISON_GREATER: {
5810 if((b_inc && CHILD(1).number() < *ass->min()) || (!b_inc && CHILD(1).number() <= *ass->min())) {set(1, 1, 0, true); b = true;}
5811 break;
5812 }
5813 case COMPARISON_EQUALS_LESS: {
5814 if(b_inc && CHILD(1).number() == *ass->min()) {ct_comp = COMPARISON_EQUALS; b = true;}
5815 else if((b_inc && CHILD(1).number() < *ass->min()) || (!b_inc && CHILD(1).number() <= *ass->min())) {clear(true); b = true;}
5816 break;
5817 }
5818 case COMPARISON_EQUALS_GREATER: {
5819 if(CHILD(1).number() <= *ass->min()) {set(1, 1, 0, true); b = true;}
5820 break;
5821 }
5822 }
5823 }
5824 if(ass && ass->max() && isComparison()) {
5825 bool b_inc = ass->includeEqualsMax();
5826 switch(ct_comp) {
5827 case COMPARISON_EQUALS: {
5828 if((b_inc && CHILD(1).number() > *ass->max()) || (!b_inc && CHILD(1).number() >= *ass->max())) {clear(true); b = true;}
5829 break;
5830 }
5831 case COMPARISON_NOT_EQUALS: {
5832 if((b_inc && CHILD(1).number() > *ass->max()) || (!b_inc && CHILD(1).number() >= *ass->max())) {set(1, 1, 0, true); b = true;}
5833 break;
5834 }
5835 case COMPARISON_LESS: {
5836 if((b_inc && CHILD(1).number() > *ass->max()) || (!b_inc && CHILD(1).number() >= *ass->max())) {set(1, 1, 0, true); b = true;}
5837 break;
5838 }
5839 case COMPARISON_GREATER: {
5840 if(CHILD(1).number() >= *ass->max()) {clear(true); b = true;}
5841 break;
5842 }
5843 case COMPARISON_EQUALS_LESS: {
5844 if(CHILD(1).number() >= *ass->max()) {set(1, 1, 0, true); b = true;}
5845 break;
5846 }
5847 case COMPARISON_EQUALS_GREATER: {
5848 if(b_inc && CHILD(1).number() == *ass->max()) {ct_comp = COMPARISON_EQUALS; b = true;}
5849 else if((b_inc && CHILD(1).number() > *ass->max()) || (!b_inc && CHILD(1).number() >= *ass->max())) {clear(true); b = true;}
5850 break;
5851 }
5852 }
5853 }
5854 }
5855 if(b) break;
5856 if(eo.approximation == APPROXIMATION_EXACT && eo.test_comparisons > 0) {
5857 bool b_intval = CALCULATOR->usesIntervalArithmetic();
5858 bool b_failed = false;
5859 EvaluationOptions eo3 = feo;
5860 eo2.approximation = APPROXIMATION_APPROXIMATE;
5861 eo3.approximation = APPROXIMATION_APPROXIMATE;
5862 eo2.test_comparisons = false;
5863 MathStructure mtest(*this);
5864 for(int i = 0; i < 2; i++) {
5865 CALCULATOR->beginTemporaryEnableIntervalArithmetic();
5866 int b_ass = (i == 0 ? 2 : contains_ass_intval(mtest));
5867 if(b_ass == 0 || !CALCULATOR->usesIntervalArithmetic()) {CALCULATOR->endTemporaryEnableIntervalArithmetic(); break;}
5868 replace_interval_unknowns(mtest, i > 0);
5869 if(i == 0 && !b_intval) fix_intervals(mtest, eo2, &b_failed);
5870 if(!b_failed) {
5871 if(i == 0 && mtest[0].isAddition() && mtest[0].size() > 1 && mtest[1].isZero()) {
5872 mtest[1] = mtest[0][0];
5873 mtest[1].negate();
5874 mtest[0].delChild(1, true);
5875 }
5876 CALCULATOR->beginTemporaryStopMessages();
5877 if(b_ass == 2) mtest[0].calculateFunctions(eo3);
5878 mtest[0].calculatesub(eo2, eo3, true);
5879 if(b_ass == 2) mtest[1].calculateFunctions(eo3);
5880 mtest[1].calculatesub(eo2, eo3, true);
5881 CALCULATOR->endTemporaryEnableIntervalArithmetic();
5882 mtest.childrenUpdated();
5883 if(CALCULATOR->endTemporaryStopMessages(NULL, NULL, MESSAGE_ERROR) == 0) {
5884 eo2.approximation = eo.approximation;
5885 eo2.test_comparisons = -1;
5886 mtest.calculatesub(eo2, feo, false);
5887 if(mtest.isNumber()) {
5888 if(mtest.isZero()) clear(true);
5889 else set(1, 1, 0, true);
5890 b = true;
5891 return b;
5892 }
5893 }
5894 } else {
5895 CALCULATOR->endTemporaryEnableIntervalArithmetic();
5896 break;
5897 }
5898 }
5899 }
5900 eo2 = eo;
5901 if(eo2.assume_denominators_nonzero == 1) eo2.assume_denominators_nonzero = false;
5902 bool mtest_new = false;
5903 MathStructure *mtest;
5904 if(!CHILD(1).isZero()) {
5905 if(!eo.isolate_x || find_x_var().isUndefined()) {
5906 CHILD(0).calculateSubtract(CHILD(1), eo2);
5907 CHILD(1).clear();
5908 mtest = &CHILD(0);
5909 mtest->ref();
5910 } else {
5911 mtest = new MathStructure(CHILD(0));
5912 mtest->calculateSubtract(CHILD(1), eo2);
5913 remove_rad_unit(*mtest, eo2);
5914 mtest_new = true;
5915 }
5916 } else {
5917 mtest = &CHILD(0);
5918 mtest->ref();
5919 }
5920 int incomp = 0;
5921 if(mtest->isAddition()) {
5922 mtest->evalSort(true);
5923 incomp = compare_check_incompability(mtest);
5924 if(incomp == 1 && !mtest_new) {
5925 mtest->unref();
5926 mtest = new MathStructure(CHILD(0));
5927 if(remove_rad_unit(*mtest, eo2)) {
5928 mtest_new = true;
5929 if(mtest->isAddition()) {
5930 mtest->evalSort(true);
5931 incomp = compare_check_incompability(mtest);
5932 }
5933 }
5934 }
5935 }
5936 if(incomp <= 0) {
5937 if(mtest_new && (ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS)) {
5938 bool a_pos = CHILD(0).representsPositive(true);
5939 bool a_nneg = a_pos || CHILD(0).representsNonNegative(true);
5940 bool a_neg = !a_nneg && CHILD(0).representsNegative(true);
5941 bool a_npos = !a_pos && (a_neg || CHILD(0).representsNonPositive(true));
5942 bool b_pos = CHILD(1).representsPositive(true);
5943 bool b_nneg = b_pos || CHILD(1).representsNonNegative(true);
5944 bool b_neg = !b_nneg && CHILD(1).representsNegative(true);
5945 bool b_npos = !b_pos && (b_neg || CHILD(1).representsNonPositive(true));
5946 if(isApproximate()) {
5947 if((a_pos && b_neg) || (a_neg && b_pos)) {
5948 incomp = 1;
5949 }
5950 } else {
5951 if((a_pos && b_npos) || (a_npos && b_pos) || (a_nneg && b_neg) || (a_neg && b_nneg)) {
5952 incomp = 1;
5953 }
5954 }
5955 } else if(incomp < 0) {
5956 mtest->unref();
5957 break;
5958 }
5959 }
5960
5961 switch(ct_comp) {
5962 case COMPARISON_EQUALS: {
5963 if(incomp > 0) {
5964 clear(true);
5965 b = true;
5966 } else if(mtest->representsZero(true)) {
5967 set(1, 1, 0, true);
5968 b = true;
5969 } else if(mtest->representsNonZero(true)) {
5970 clear(true);
5971 b = true;
5972 }
5973 break;
5974 }
5975 case COMPARISON_NOT_EQUALS: {
5976 if(incomp > 0) {
5977 set(1, 1, 0, true);
5978 b = true;
5979 } else if(mtest->representsNonZero(true)) {
5980 set(1, 1, 0, true);
5981 b = true;
5982 } else if(mtest->representsZero(true)) {
5983 clear(true);
5984 b = true;
5985 }
5986 break;
5987 }
5988 case COMPARISON_LESS: {
5989 if(incomp > 0) {
5990 } else if(mtest->representsNegative(true)) {
5991 set(1, 1, 0, true);
5992 b = true;
5993 } else if(mtest->representsNonNegative(true)) {
5994 clear(true);
5995 b = true;
5996 }
5997 break;
5998 }
5999 case COMPARISON_GREATER: {
6000 if(incomp > 0) {
6001 } else if(mtest->representsPositive(true)) {
6002 set(1, 1, 0, true);
6003 b = true;
6004 } else if(mtest->representsNonPositive(true)) {
6005 clear(true);
6006 b = true;
6007 }
6008 break;
6009 }
6010 case COMPARISON_EQUALS_LESS: {
6011 if(incomp > 0) {
6012 } else if(mtest->representsNonPositive(true)) {
6013 set(1, 1, 0, true);
6014 b = true;
6015 } else if(mtest->representsPositive(true)) {
6016 clear(true);
6017 b = true;
6018 }
6019 break;
6020 }
6021 case COMPARISON_EQUALS_GREATER: {
6022 if(incomp > 0) {
6023 } else if(mtest->representsNonNegative(true)) {
6024 set(1, 1, 0, true);
6025 b = true;
6026 } else if(mtest->representsNegative(true)) {
6027 clear(true);
6028 b = true;
6029 }
6030 break;
6031 }
6032 }
6033 mtest->unref();
6034 break;
6035 }
6036 case STRUCT_FUNCTION: {
6037 // always calculate certain functions (introduced by operations outside of functions)
6038 if(o_function->id() == FUNCTION_ID_ABS || o_function->id() == FUNCTION_ID_ROOT || o_function->id() == FUNCTION_ID_INTERVAL || o_function->id() == FUNCTION_ID_UNCERTAINTY || o_function->id() == FUNCTION_ID_SIGNUM || o_function->id() == FUNCTION_ID_DIRAC || o_function->id() == FUNCTION_ID_HEAVISIDE) {
6039 b = calculateFunctions(eo, false);
6040 if(b) {
6041 calculatesub(eo, feo, true, mparent, index_this);
6042 break;
6043 }
6044 } else if(o_function->id() == FUNCTION_ID_STRIP_UNITS) {
6045 b = calculateFunctions(eo, false);
6046 if(b) calculatesub(eo, feo, true, mparent, index_this);
6047 break;
6048 }
6049 }
6050 default: {
6051 if(recursive) {
6052 for(size_t i = 0; i < SIZE; i++) {
6053 if(CHILD(i).calculatesub(eo, feo, true, this, i)) b = true;
6054 }
6055 CHILDREN_UPDATED;
6056 }
6057 if(eo.sync_units && syncUnits(eo.sync_nonlinear_unit_relations, NULL, true, feo)) {
6058 unformat(eo);
6059 if(recursive) {
6060 for(size_t i = 0; i < SIZE; i++) {
6061 if(CHILD(i).calculatesub(eo, feo, true, this, i)) b = true;
6062 }
6063 CHILDREN_UPDATED;
6064 }
6065 }
6066 }
6067 }
6068 return b;
6069 }
6070
6071 #define MERGE_INDEX(FUNC, TRY_LABEL) bool b = false;\
6072 TRY_LABEL:\
6073 for(size_t i = 0; i < index; i++) {\
6074 if(CALCULATOR->aborted()) break; \
6075 int r = CHILD(i).FUNC(CHILD(index), eo, this, i, index);\
6076 if(r == 0) {\
6077 SWAP_CHILDREN(i, index);\
6078 r = CHILD(i).FUNC(CHILD(index), eo, this, i, index, true);\
6079 if(r < 1) {\
6080 SWAP_CHILDREN(i, index);\
6081 } else if(r == 2) {\
6082 r = 3;\
6083 } else if(r == 3) {\
6084 r = 2;\
6085 }\
6086 }\
6087 if(r >= 1) {\
6088 ERASE(index);\
6089 if(!b && r == 2) {\
6090 b = true;\
6091 index = SIZE;\
6092 break;\
6093 } else {\
6094 b = true;\
6095 index = i;\
6096 goto TRY_LABEL;\
6097 }\
6098 }\
6099 }\
6100 for(size_t i = index + 1; i < SIZE; i++) {\
6101 if(CALCULATOR->aborted()) break; \
6102 int r = CHILD(index).FUNC(CHILD(i), eo, this, index, i);\
6103 if(r == 0) {\
6104 SWAP_CHILDREN(index, i);\
6105 r = CHILD(index).FUNC(CHILD(i), eo, this, index, i, true);\
6106 if(r < 1) {\
6107 SWAP_CHILDREN(index, i);\
6108 } else if(r == 2) {\
6109 r = 3;\
6110 } else if(r == 3) {\
6111 r = 2;\
6112 }\
6113 }\
6114 if(r >= 1) {\
6115 ERASE(i);\
6116 if(!b && r == 3) {\
6117 b = true;\
6118 break;\
6119 }\
6120 b = true;\
6121 if(r != 2) {\
6122 goto TRY_LABEL;\
6123 }\
6124 i--;\
6125 }\
6126 }
6127
6128 #define MERGE_INDEX2 if(b && check_size) {\
6129 if(SIZE == 1) {\
6130 setToChild(1, false, mparent, index_this + 1);\
6131 } else if(SIZE == 0) {\
6132 clear(true);\
6133 } else {\
6134 evalSort();\
6135 }\
6136 return true;\
6137 } else {\
6138 evalSort();\
6139 return b;\
6140 }
6141
6142
calculateMergeIndex(size_t index,const EvaluationOptions & eo,const EvaluationOptions & feo,MathStructure * mparent,size_t index_this)6143 bool MathStructure::calculateMergeIndex(size_t index, const EvaluationOptions &eo, const EvaluationOptions &feo, MathStructure *mparent, size_t index_this) {
6144 switch(m_type) {
6145 case STRUCT_MULTIPLICATION: {
6146 return calculateMultiplyIndex(index, eo, true, mparent, index_this);
6147 }
6148 case STRUCT_ADDITION: {
6149 return calculateAddIndex(index, eo, true, mparent, index_this);
6150 }
6151 case STRUCT_POWER: {
6152 return calculateRaiseExponent(eo, mparent, index_this);
6153 }
6154 case STRUCT_LOGICAL_AND: {
6155 return calculateLogicalAndIndex(index, eo, true, mparent, index_this);
6156 }
6157 case STRUCT_LOGICAL_OR: {
6158 return calculateLogicalOrIndex(index, eo, true, mparent, index_this);
6159 }
6160 case STRUCT_LOGICAL_XOR: {
6161 return calculateLogicalXorLast(eo, mparent, index_this);
6162 }
6163 case STRUCT_BITWISE_AND: {
6164 return calculateBitwiseAndIndex(index, eo, true, mparent, index_this);
6165 }
6166 case STRUCT_BITWISE_OR: {
6167 return calculateBitwiseOrIndex(index, eo, true, mparent, index_this);
6168 }
6169 case STRUCT_BITWISE_XOR: {
6170 return calculateBitwiseXorIndex(index, eo, true, mparent, index_this);
6171 }
6172 default: {}
6173 }
6174 return calculatesub(eo, feo, false, mparent, index_this);
6175 }
calculateLogicalOrLast(const EvaluationOptions & eo,bool check_size,MathStructure * mparent,size_t index_this)6176 bool MathStructure::calculateLogicalOrLast(const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) {
6177 return calculateLogicalOrIndex(SIZE - 1, eo, check_size, mparent, index_this);
6178 }
calculateLogicalOrIndex(size_t index,const EvaluationOptions & eo,bool check_size,MathStructure * mparent,size_t index_this)6179 bool MathStructure::calculateLogicalOrIndex(size_t index, const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) {
6180
6181 if(index >= SIZE || !isLogicalOr()) {
6182 CALCULATOR->error(true, "calculateLogicalOrIndex() error: %s. %s", format_and_print(*this).c_str(), _("This is a bug. Please report it."), NULL);
6183 return false;
6184 }
6185
6186 MERGE_INDEX(merge_logical_or, try_logical_or_index)
6187
6188 if(b && check_size) {
6189 if(SIZE == 1) {
6190 if(CHILD(0).representsBoolean() || (mparent && !mparent->isMultiplication() && mparent->representsBoolean())) {
6191 setToChild(1, false, mparent, index_this + 1);
6192 } else if(CHILD(0).representsPositive()) {
6193 clear(true);
6194 o_number.setTrue();
6195 } else if(CHILD(0).representsNonPositive()) {
6196 clear(true);
6197 o_number.setFalse();
6198 } else {
6199 APPEND(m_zero);
6200 m_type = STRUCT_COMPARISON;
6201 ct_comp = COMPARISON_GREATER;
6202 }
6203 } else if(SIZE == 0) {
6204 clear(true);
6205 } else {
6206 evalSort();
6207 }
6208 return true;
6209 } else {
6210 evalSort();
6211 return false;
6212 }
6213
6214 }
calculateLogicalOr(const MathStructure & mor,const EvaluationOptions & eo,MathStructure * mparent,size_t index_this)6215 bool MathStructure::calculateLogicalOr(const MathStructure &mor, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) {
6216 add(mor, OPERATION_LOGICAL_OR, true);
6217 LAST.evalSort();
6218 return calculateLogicalOrIndex(SIZE - 1, eo, true, mparent, index_this);
6219 }
calculateLogicalXorLast(const EvaluationOptions & eo,MathStructure * mparent,size_t index_this)6220 bool MathStructure::calculateLogicalXorLast(const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) {
6221
6222 if(!isLogicalXor()) {
6223 CALCULATOR->error(true, "calculateLogicalXorLast() error: %s. %s", format_and_print(*this).c_str(), _("This is a bug. Please report it."), NULL);
6224 return false;
6225 }
6226 if(CHILD(0).merge_logical_xor(CHILD(1), eo, this, 0, 1) >= 1) {
6227 if(CHILD(0).representsBoolean() || (mparent && !mparent->isMultiplication() && mparent->representsBoolean())) {
6228 setToChild(1, false, mparent, index_this + 1);
6229 } else if(CHILD(0).representsPositive()) {
6230 clear(true);
6231 o_number.setTrue();
6232 } else if(CHILD(0).representsNonPositive()) {
6233 clear(true);
6234 o_number.setFalse();
6235 } else {
6236 APPEND(m_zero);
6237 m_type = STRUCT_COMPARISON;
6238 ct_comp = COMPARISON_GREATER;
6239 }
6240 return true;
6241 }
6242 return false;
6243
6244 }
calculateLogicalXor(const MathStructure & mxor,const EvaluationOptions & eo,MathStructure * mparent,size_t index_this)6245 bool MathStructure::calculateLogicalXor(const MathStructure &mxor, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) {
6246 add(mxor, OPERATION_LOGICAL_XOR);
6247 LAST.evalSort();
6248 return calculateLogicalXorLast(eo, mparent, index_this);
6249 }
calculateLogicalAndLast(const EvaluationOptions & eo,bool check_size,MathStructure * mparent,size_t index_this)6250 bool MathStructure::calculateLogicalAndLast(const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) {
6251 return calculateLogicalAndIndex(SIZE - 1, eo, check_size, mparent, index_this);
6252 }
calculateLogicalAndIndex(size_t index,const EvaluationOptions & eo,bool check_size,MathStructure * mparent,size_t index_this)6253 bool MathStructure::calculateLogicalAndIndex(size_t index, const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) {
6254
6255 if(index >= SIZE || !isLogicalAnd()) {
6256 CALCULATOR->error(true, "calculateLogicalAndIndex() error: %s. %s", format_and_print(*this).c_str(), _("This is a bug. Please report it."), NULL);
6257 return false;
6258 }
6259
6260 MERGE_INDEX(merge_logical_and, try_logical_and_index)
6261
6262 if(b && check_size) {
6263 if(SIZE == 1) {
6264 if(CHILD(0).representsBoolean() || (mparent && !mparent->isMultiplication() && mparent->representsBoolean())) {
6265 setToChild(1, false, mparent, index_this + 1);
6266 } else if(CHILD(0).representsPositive()) {
6267 clear(true);
6268 o_number.setTrue();
6269 } else if(CHILD(0).representsNonPositive()) {
6270 clear(true);
6271 o_number.setFalse();
6272 } else {
6273 APPEND(m_zero);
6274 m_type = STRUCT_COMPARISON;
6275 ct_comp = COMPARISON_GREATER;
6276 }
6277 } else if(SIZE == 0) {
6278 clear(true);
6279 } else {
6280 evalSort();
6281 }
6282 return true;
6283 } else {
6284 evalSort();
6285 return false;
6286 }
6287
6288 }
calculateLogicalAnd(const MathStructure & mand,const EvaluationOptions & eo,MathStructure * mparent,size_t index_this)6289 bool MathStructure::calculateLogicalAnd(const MathStructure &mand, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) {
6290 add(mand, OPERATION_LOGICAL_AND, true);
6291 LAST.evalSort();
6292 return calculateLogicalAndIndex(SIZE - 1, eo, true, mparent, index_this);
6293 }
calculateInverse(const EvaluationOptions & eo,MathStructure * mparent,size_t index_this)6294 bool MathStructure::calculateInverse(const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) {
6295 return calculateRaise(m_minus_one, eo, mparent, index_this);
6296 }
calculateNegate(const EvaluationOptions & eo,MathStructure * mparent,size_t index_this)6297 bool MathStructure::calculateNegate(const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) {
6298 if(m_type == STRUCT_NUMBER) {
6299 Number nr(o_number);
6300 if(nr.negate() && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate())) {
6301 o_number = nr;
6302 numberUpdated();
6303 return true;
6304 }
6305 if(!isMultiplication()) transform(STRUCT_MULTIPLICATION);
6306 PREPEND(m_minus_one);
6307 return false;
6308 }
6309 if(!isMultiplication()) transform(STRUCT_MULTIPLICATION);
6310 PREPEND(m_minus_one);
6311 return calculateMultiplyIndex(0, eo, true, mparent, index_this);
6312 }
calculateBitwiseNot(const EvaluationOptions & eo,MathStructure * mparent,size_t index_this)6313 bool MathStructure::calculateBitwiseNot(const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) {
6314 transform(STRUCT_LOGICAL_NOT);
6315 return calculatesub(eo, eo, false, mparent, index_this);
6316 }
calculateLogicalNot(const EvaluationOptions & eo,MathStructure * mparent,size_t index_this)6317 bool MathStructure::calculateLogicalNot(const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) {
6318 transform(STRUCT_BITWISE_NOT);
6319 return calculatesub(eo, eo, false, mparent, index_this);
6320 }
calculateRaiseExponent(const EvaluationOptions & eo,MathStructure * mparent,size_t index_this)6321 bool MathStructure::calculateRaiseExponent(const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) {
6322 if(!isPower()) {
6323 CALCULATOR->error(true, "calculateRaiseExponent() error: %s. %s", format_and_print(*this).c_str(), _("This is a bug. Please report it."), NULL);
6324 return false;
6325 }
6326 if(CHILD(0).merge_power(CHILD(1), eo, this, 0, 1) >= 1) {
6327 setToChild(1, false, mparent, index_this + 1);
6328 return true;
6329 }
6330 return false;
6331 }
calculateRaise(const MathStructure & mexp,const EvaluationOptions & eo,MathStructure * mparent,size_t index_this)6332 bool MathStructure::calculateRaise(const MathStructure &mexp, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) {
6333 if(mexp.type() == STRUCT_NUMBER && m_type == STRUCT_NUMBER) {
6334 Number nr(o_number);
6335 if(nr.raise(mexp.number(), eo.approximation < APPROXIMATION_APPROXIMATE) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || mexp.number().isApproximate()) && (eo.allow_complex || !nr.isComplex() || o_number.isComplex() || mexp.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || o_number.includesInfinity() || mexp.number().includesInfinity())) {
6336 o_number = nr;
6337 numberUpdated();
6338 return true;
6339 }
6340 }
6341 raise(mexp);
6342 LAST.evalSort();
6343 return calculateRaiseExponent(eo, mparent, index_this);
6344 }
calculateBitwiseAndLast(const EvaluationOptions & eo,bool check_size,MathStructure * mparent,size_t index_this)6345 bool MathStructure::calculateBitwiseAndLast(const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) {
6346 return calculateBitwiseAndIndex(SIZE - 1, eo, check_size, mparent, index_this);
6347 }
calculateBitwiseAndIndex(size_t index,const EvaluationOptions & eo,bool check_size,MathStructure * mparent,size_t index_this)6348 bool MathStructure::calculateBitwiseAndIndex(size_t index, const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) {
6349
6350 if(index >= SIZE || !isBitwiseAnd()) {
6351 CALCULATOR->error(true, "calculateBitwiseAndIndex() error: %s. %s", format_and_print(*this).c_str(), _("This is a bug. Please report it."), NULL);
6352 return false;
6353 }
6354
6355 MERGE_INDEX(merge_bitwise_and, try_bitwise_and_index)
6356 MERGE_INDEX2
6357
6358 }
calculateBitwiseAnd(const MathStructure & mand,const EvaluationOptions & eo,MathStructure * mparent,size_t index_this)6359 bool MathStructure::calculateBitwiseAnd(const MathStructure &mand, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) {
6360 add(mand, OPERATION_BITWISE_AND, true);
6361 LAST.evalSort();
6362 return calculateBitwiseAndIndex(SIZE - 1, eo, true, mparent, index_this);
6363 }
calculateBitwiseOrLast(const EvaluationOptions & eo,bool check_size,MathStructure * mparent,size_t index_this)6364 bool MathStructure::calculateBitwiseOrLast(const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) {
6365 return calculateBitwiseOrIndex(SIZE - 1, eo, check_size, mparent, index_this);
6366 }
calculateBitwiseOrIndex(size_t index,const EvaluationOptions & eo,bool check_size,MathStructure * mparent,size_t index_this)6367 bool MathStructure::calculateBitwiseOrIndex(size_t index, const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) {
6368
6369 if(index >= SIZE || !isBitwiseOr()) {
6370 CALCULATOR->error(true, "calculateBitwiseOrIndex() error: %s. %s", format_and_print(*this).c_str(), _("This is a bug. Please report it."), NULL);
6371 return false;
6372 }
6373
6374 MERGE_INDEX(merge_bitwise_or, try_bitwise_or_index)
6375 MERGE_INDEX2
6376
6377 }
calculateBitwiseOr(const MathStructure & mor,const EvaluationOptions & eo,MathStructure * mparent,size_t index_this)6378 bool MathStructure::calculateBitwiseOr(const MathStructure &mor, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) {
6379 add(mor, OPERATION_BITWISE_OR, true);
6380 LAST.evalSort();
6381 return calculateBitwiseOrIndex(SIZE - 1, eo, true, mparent, index_this);
6382 }
calculateBitwiseXorLast(const EvaluationOptions & eo,bool check_size,MathStructure * mparent,size_t index_this)6383 bool MathStructure::calculateBitwiseXorLast(const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) {
6384 return calculateBitwiseXorIndex(SIZE - 1, eo, check_size, mparent, index_this);
6385 }
calculateBitwiseXorIndex(size_t index,const EvaluationOptions & eo,bool check_size,MathStructure * mparent,size_t index_this)6386 bool MathStructure::calculateBitwiseXorIndex(size_t index, const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) {
6387
6388 if(index >= SIZE || !isBitwiseXor()) {
6389 CALCULATOR->error(true, "calculateBitwiseXorIndex() error: %s. %s", format_and_print(*this).c_str(), _("This is a bug. Please report it."), NULL);
6390 return false;
6391 }
6392
6393 MERGE_INDEX(merge_bitwise_xor, try_bitwise_xor_index)
6394 MERGE_INDEX2
6395
6396 }
calculateBitwiseXor(const MathStructure & mxor,const EvaluationOptions & eo,MathStructure * mparent,size_t index_this)6397 bool MathStructure::calculateBitwiseXor(const MathStructure &mxor, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) {
6398 add(mxor, OPERATION_BITWISE_XOR, true);
6399 LAST.evalSort();
6400 return calculateBitwiseXorIndex(SIZE - 1, eo, true, mparent, index_this);
6401 }
calculateMultiplyLast(const EvaluationOptions & eo,bool check_size,MathStructure * mparent,size_t index_this)6402 bool MathStructure::calculateMultiplyLast(const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) {
6403 return calculateMultiplyIndex(SIZE - 1, eo, check_size, mparent, index_this);
6404 }
calculateMultiplyIndex(size_t index,const EvaluationOptions & eo,bool check_size,MathStructure * mparent,size_t index_this)6405 bool MathStructure::calculateMultiplyIndex(size_t index, const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) {
6406
6407 if(index >= SIZE || !isMultiplication()) {
6408 CALCULATOR->error(true, "calculateMultiplyIndex() error: %s. %s", format_and_print(*this).c_str(), _("This is a bug. Please report it."), NULL);
6409 return false;
6410 }
6411
6412 bool b = false;
6413 try_multiply_matrix_index:
6414 bool b_matrix = !CHILD(index).representsNonMatrix();
6415 if(index > 0) {
6416 for(size_t i = index - 1; ; i--) {
6417 if(CALCULATOR->aborted()) break;
6418 int r = CHILD(i).merge_multiplication(CHILD(index), eo, this, i, index);
6419 if(r == 0) {
6420 SWAP_CHILDREN(i, index);
6421 r = CHILD(i).merge_multiplication(CHILD(index), eo, this, i, index, true);
6422 if(r < 1) {
6423 SWAP_CHILDREN(i, index);
6424 } else if(r == 2) {
6425 r = 3;
6426 } else if(r == 3) {
6427 r = 2;
6428 }
6429 }
6430 if(r >= 1) {
6431 ERASE(index);
6432 if(!b && r == 2) {
6433 b = true;
6434 index = SIZE;
6435 break;
6436 } else {
6437 b = true;
6438 index = i;
6439 goto try_multiply_matrix_index;
6440 }
6441 }
6442 if(i == 0) break;
6443 if(b_matrix && !CHILD(i).representsNonMatrix()) break;
6444 }
6445 }
6446
6447 bool had_matrix = false;
6448 for(size_t i = index + 1; i < SIZE; i++) {
6449 if(had_matrix && !CHILD(i).representsNonMatrix()) continue;
6450 if(CALCULATOR->aborted()) break;
6451 int r = CHILD(index).merge_multiplication(CHILD(i), eo, this, index, i);
6452 if(r == 0) {
6453 SWAP_CHILDREN(index, i);
6454 r = CHILD(index).merge_multiplication(CHILD(i), eo, this, index, i, true);
6455 if(r < 1) {
6456 SWAP_CHILDREN(index, i);
6457 } else if(r == 2) {
6458 r = 3;
6459 } else if(r == 3) {
6460 r = 2;
6461 }
6462 }
6463 if(r >= 1) {
6464 ERASE(i);
6465 if(!b && r == 3) {
6466 b = true;
6467 break;
6468 }
6469 b = true;
6470 if(r != 2) {
6471 goto try_multiply_matrix_index;
6472 }
6473 i--;
6474 }
6475 if(i == SIZE - 1) break;
6476 if(b_matrix && !CHILD(i).representsNonMatrix()) had_matrix = true;
6477 }
6478
6479 MERGE_INDEX2
6480
6481 }
calculateMultiply(const MathStructure & mmul,const EvaluationOptions & eo,MathStructure * mparent,size_t index_this)6482 bool MathStructure::calculateMultiply(const MathStructure &mmul, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) {
6483 if(mmul.type() == STRUCT_NUMBER && m_type == STRUCT_NUMBER) {
6484 Number nr(o_number);
6485 if(nr.multiply(mmul.number()) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || mmul.number().isApproximate()) && (eo.allow_complex || !nr.isComplex() || o_number.isComplex() || mmul.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || o_number.includesInfinity() || mmul.number().includesInfinity())) {
6486 o_number = nr;
6487 numberUpdated();
6488 return true;
6489 }
6490 }
6491 multiply(mmul, true);
6492 LAST.evalSort();
6493 return calculateMultiplyIndex(SIZE - 1, eo, true, mparent, index_this);
6494 }
calculateDivide(const MathStructure & mdiv,const EvaluationOptions & eo,MathStructure * mparent,size_t index_this)6495 bool MathStructure::calculateDivide(const MathStructure &mdiv, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) {
6496 if(mdiv.type() == STRUCT_NUMBER && m_type == STRUCT_NUMBER) {
6497 Number nr(o_number);
6498 if(nr.divide(mdiv.number()) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || mdiv.number().isApproximate()) && (eo.allow_complex || !nr.isComplex() || o_number.isComplex() || mdiv.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || o_number.includesInfinity() || mdiv.number().includesInfinity())) {
6499 o_number = nr;
6500 numberUpdated();
6501 return true;
6502 }
6503 }
6504 MathStructure *mmul = new MathStructure(mdiv);
6505 mmul->evalSort();
6506 multiply_nocopy(mmul, true);
6507 LAST.calculateInverse(eo, this, SIZE - 1);
6508 return calculateMultiplyIndex(SIZE - 1, eo, true, mparent, index_this);
6509 }
calculateAddLast(const EvaluationOptions & eo,bool check_size,MathStructure * mparent,size_t index_this)6510 bool MathStructure::calculateAddLast(const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) {
6511 return calculateAddIndex(SIZE - 1, eo, check_size, mparent, index_this);
6512 }
calculateAddIndex(size_t index,const EvaluationOptions & eo,bool check_size,MathStructure * mparent,size_t index_this)6513 bool MathStructure::calculateAddIndex(size_t index, const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) {
6514
6515 if(index >= SIZE || !isAddition()) {
6516 CALCULATOR->error(true, "calculateAddIndex() error: %s. %s", format_and_print(*this).c_str(), _("This is a bug. Please report it."), NULL);
6517 return false;
6518 }
6519
6520 MERGE_INDEX(merge_addition, try_add_index)
6521 MERGE_INDEX2
6522
6523 }
calculateAdd(const MathStructure & madd,const EvaluationOptions & eo,MathStructure * mparent,size_t index_this)6524 bool MathStructure::calculateAdd(const MathStructure &madd, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) {
6525 if(madd.type() == STRUCT_NUMBER && m_type == STRUCT_NUMBER) {
6526 Number nr(o_number);
6527 if(nr.add(madd.number()) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || madd.number().isApproximate())) {
6528 o_number = nr;
6529 numberUpdated();
6530 return true;
6531 }
6532 }
6533 add(madd, true);
6534 LAST.evalSort();
6535 return calculateAddIndex(SIZE - 1, eo, true, mparent, index_this);
6536 }
calculateSubtract(const MathStructure & msub,const EvaluationOptions & eo,MathStructure * mparent,size_t index_this)6537 bool MathStructure::calculateSubtract(const MathStructure &msub, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) {
6538 if(msub.type() == STRUCT_NUMBER && m_type == STRUCT_NUMBER) {
6539 Number nr(o_number);
6540 if(nr.subtract(msub.number()) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || msub.number().isApproximate())) {
6541 o_number = nr;
6542 numberUpdated();
6543 return true;
6544 }
6545 }
6546 MathStructure *madd = new MathStructure(msub);
6547 madd->evalSort();
6548 add_nocopy(madd, true);
6549 LAST.calculateNegate(eo, this, SIZE - 1);
6550 return calculateAddIndex(SIZE - 1, eo, true, mparent, index_this);
6551 }
6552
calculateFunctions(const EvaluationOptions & eo,bool recursive,bool do_unformat)6553 bool MathStructure::calculateFunctions(const EvaluationOptions &eo, bool recursive, bool do_unformat) {
6554
6555 if(m_type == STRUCT_FUNCTION && o_function != eo.protected_function) {
6556
6557 if(function_value) {
6558 // clear stored function value (presently not used)
6559 function_value->unref();
6560 function_value = NULL;
6561 }
6562
6563 // test if the number of arguments (children) is appropriate for the function
6564 if(!o_function->testArgumentCount(SIZE)) {
6565 return false;
6566 }
6567
6568 if(o_function->maxargs() > -1 && (long int) SIZE > o_function->maxargs()) {
6569 if(o_function->maxargs() == 1 && o_function->getArgumentDefinition(1) && o_function->getArgumentDefinition(1)->handlesVector()) {
6570 // for functions which takes exactly one argument: if there are additional children calculate the function separately for each child and place results in vector
6571 bool b = false;
6572 for(size_t i2 = 0; i2 < CHILD(0).size(); i2++) {
6573 CHILD(0)[i2].transform(o_function);
6574 if(CHILD(0)[i2].calculateFunctions(eo, recursive, do_unformat)) b = true;
6575 CHILD(0).childUpdated(i2 + 1);
6576 }
6577 SET_CHILD_MAP(0)
6578 return b;
6579 }
6580 // remove unused arguments/children
6581 REDUCE(o_function->maxargs());
6582 }
6583 m_type = STRUCT_VECTOR;
6584 Argument *arg = NULL, *last_arg = NULL;
6585 int last_i = 0;
6586
6587 for(size_t i = 0; i < SIZE; i++) {
6588 arg = o_function->getArgumentDefinition(i + 1);
6589 if(arg) {
6590 last_arg = arg;
6591 last_i = i;
6592 if(i > 0 && arg->type() == ARGUMENT_TYPE_SYMBOLIC && (CHILD(i).isZero() || CHILD(i).isUndefined())) {
6593 // argument type is symbol and value is zero or undefined, search the first argument/child for symbols
6594 CHILD(i).set(CHILD(0).find_x_var(), true);
6595 if(CHILD(i).isUndefined() && CHILD(0).isVariable() && CHILD(0).variable()->isKnown()) CHILD(i).set(((KnownVariable*) CHILD(0).variable())->get().find_x_var(), true);
6596 if(CHILD(i).isUndefined()) {
6597 // no symbol found: calculate the argument/child and try again
6598 CALCULATOR->beginTemporaryStopMessages();
6599 MathStructure mtest(CHILD(0));
6600 mtest.eval(eo);
6601 CHILD(i).set(mtest.find_x_var(), true);
6602 CALCULATOR->endTemporaryStopMessages();
6603 }
6604 if(CHILD(i).isUndefined()) {
6605 CALCULATOR->error(false, _("No unknown variable/symbol was found."), NULL);
6606 CHILD(i).set(CALCULATOR->getVariableById(VARIABLE_ID_X), true);
6607 }
6608 }
6609 // test if argument/child can be used by function
6610 if(!arg->test(CHILD(i), i + 1, o_function, eo)) {
6611 if(arg->handlesVector() && CHILD(i).isVector()) {
6612 // calculate the function separately for each child of vector
6613 bool b = false;
6614 for(size_t i2 = 0; i2 < CHILD(i).size(); i2++) {
6615 CHILD(i)[i2].transform(o_function);
6616 for(size_t i3 = 0; i3 < SIZE; i3++) {
6617 if(i3 < i) CHILD(i)[i2].insertChild(CHILD(i3), i3 + 1);
6618 else if(i3 > i) CHILD(i)[i2].addChild(CHILD(i3));
6619 }
6620 if(CHILD(i)[i2].calculateFunctions(eo, recursive, do_unformat)) b = true;
6621 CHILD(i).childUpdated(i2 + 1);
6622 }
6623 SET_CHILD_MAP(i);
6624 return b;
6625 }
6626 // argument/child did not fulfil criteria
6627 m_type = STRUCT_FUNCTION;
6628 CHILD_UPDATED(i);
6629 return false;
6630 } else {
6631 CHILD_UPDATED(i);
6632 }
6633 if(arg->handlesVector()) {
6634 if(arg->tests() && !CHILD(i).isVector() && !CHILD(i).representsScalar()) {
6635 CHILD(i).eval(eo);
6636 CHILD_UPDATED(i);
6637 }
6638 if(CHILD(i).isVector()) {
6639 bool b = false;
6640 // calculate the function separately for each child of vector
6641 for(size_t i2 = 0; i2 < CHILD(i).size(); i2++) {
6642 CHILD(i)[i2].transform(o_function);
6643 for(size_t i3 = 0; i3 < SIZE; i3++) {
6644 if(i3 < i) CHILD(i)[i2].insertChild(CHILD(i3), i3 + 1);
6645 else if(i3 > i) CHILD(i)[i2].addChild(CHILD(i3));
6646 }
6647 if(CHILD(i)[i2].calculateFunctions(eo, recursive, do_unformat)) b = true;
6648 CHILD(i).childUpdated(i2 + 1);
6649 }
6650 SET_CHILD_MAP(i);
6651 return b;
6652 }
6653 }
6654 }
6655 }
6656
6657 if(last_arg && o_function->maxargs() < 0 && last_i >= o_function->minargs()) {
6658 // use the last argument to test additional arguments (if number of arguments is unlimited and last argument was above minimum number of arguments)
6659 for(size_t i = last_i + 1; i < SIZE; i++) {
6660 if(!last_arg->test(CHILD(i), i + 1, o_function, eo)) {
6661 m_type = STRUCT_FUNCTION;
6662 CHILD_UPDATED(i);
6663 return false;
6664 } else {
6665 CHILD_UPDATED(i);
6666 }
6667 }
6668 }
6669
6670 if(!o_function->testCondition(*this)) {
6671 m_type = STRUCT_FUNCTION;
6672 return false;
6673 }
6674 MathStructure *mstruct = new MathStructure();
6675 int ret = o_function->calculate(*mstruct, *this, eo);
6676 if(ret > 0) {
6677 // function calculation was successful
6678 set_nocopy(*mstruct, true);
6679 if(recursive) calculateFunctions(eo);
6680 mstruct->unref();
6681 if(do_unformat) unformat(eo);
6682 return true;
6683 } else {
6684 // function calculation failed
6685 if(ret < 0) {
6686 // updated argument/child was returned
6687 ret = -ret;
6688 if(o_function->maxargs() > 0 && ret > o_function->maxargs()) {
6689 if(mstruct->isVector()) {
6690 if(do_unformat) mstruct->unformat(eo);
6691 for(size_t arg_i = 1; arg_i <= SIZE && arg_i <= mstruct->size(); arg_i++) {
6692 mstruct->getChild(arg_i)->ref();
6693 setChild_nocopy(mstruct->getChild(arg_i), arg_i);
6694 }
6695 }
6696 } else if(ret <= (long int) SIZE) {
6697 if(do_unformat) mstruct->unformat(eo);
6698 mstruct->ref();
6699 setChild_nocopy(mstruct, ret);
6700 }
6701 }
6702 /*if(eo.approximation == APPROXIMATION_EXACT) {
6703 mstruct->clear();
6704 EvaluationOptions eo2 = eo;
6705 eo2.approximation = APPROXIMATION_APPROXIMATE;
6706 CALCULATOR->beginTemporaryStopMessages();
6707 if(o_function->calculate(*mstruct, *this, eo2) > 0) {
6708 function_value = mstruct;
6709 function_value->ref();
6710 function_value->calculateFunctions(eo2);
6711 }
6712 if(CALCULATOR->endTemporaryStopMessages() > 0 && function_value) {
6713 function_value->unref();
6714 function_value = NULL;
6715 }
6716 }*/
6717 m_type = STRUCT_FUNCTION;
6718 mstruct->unref();
6719 for(size_t i = 0; i < SIZE; i++) {
6720 arg = o_function->getArgumentDefinition(i + 1);
6721 if(arg && arg->handlesVector()) {
6722 if(!CHILD(i).isVector()) {
6723 CHILD(i).calculatesub(eo, eo, false);
6724 if(!CHILD(i).isVector()) return false;
6725 }
6726 // calculate the function separately for each child of vector
6727 bool b = false;
6728 for(size_t i2 = 0; i2 < CHILD(i).size(); i2++) {
6729 CHILD(i)[i2].transform(o_function);
6730 for(size_t i3 = 0; i3 < SIZE; i3++) {
6731 if(i3 < i) CHILD(i)[i2].insertChild(CHILD(i3), i3 + 1);
6732 else if(i3 > i) CHILD(i)[i2].addChild(CHILD(i3));
6733 }
6734 if(CHILD(i)[i2].calculateFunctions(eo, recursive, do_unformat)) b = true;
6735 CHILD(i).childUpdated(i2 + 1);
6736 }
6737 SET_CHILD_MAP(i);
6738 return b;
6739 }
6740 }
6741 return false;
6742 }
6743 }
6744 bool b = false;
6745 if(recursive) {
6746 for(size_t i = 0; i < SIZE; i++) {
6747 if(CALCULATOR->aborted()) break;
6748 if(CHILD(i).calculateFunctions(eo, recursive, do_unformat)) {
6749 CHILD_UPDATED(i);
6750 b = true;
6751 }
6752 }
6753 }
6754 return b;
6755
6756 }
6757
6758 int evalSortCompare(const MathStructure &mstruct1, const MathStructure &mstruct2, const MathStructure &parent, bool b_abs = false);
evalSortCompare(const MathStructure & mstruct1,const MathStructure & mstruct2,const MathStructure & parent,bool b_abs)6759 int evalSortCompare(const MathStructure &mstruct1, const MathStructure &mstruct2, const MathStructure &parent, bool b_abs) {
6760 if(parent.isMultiplication()) {
6761 if((!mstruct1.representsNonMatrix() && !mstruct2.representsScalar()) || (!mstruct2.representsNonMatrix() && !mstruct1.representsScalar())) {
6762 return 0;
6763 }
6764 }
6765 if(b_abs || parent.isAddition()) {
6766 if(mstruct1.isMultiplication() && mstruct1.size() > 0) {
6767 size_t start = 0;
6768 while(mstruct1[start].isNumber() && mstruct1.size() > start + 1) {
6769 start++;
6770 }
6771 int i2;
6772 if(mstruct2.isMultiplication()) {
6773 if(mstruct2.size() < 1) return -1;
6774 size_t start2 = 0;
6775 while(mstruct2[start2].isNumber() && mstruct2.size() > start2 + 1) {
6776 start2++;
6777 }
6778 for(size_t i = 0; ; i++) {
6779 if(i + start2 >= mstruct2.size()) {
6780 if(i + start >= mstruct1.size()) {
6781 if(start2 == start) {
6782 for(size_t i3 = 0; i3 < start; i3++) {
6783 i2 = evalSortCompare(mstruct1[i3], mstruct2[i3], parent, b_abs);
6784 if(i2 != 0) return i2;
6785 }
6786 return 0;
6787 }
6788 if(start2 > start) return -1;
6789 }
6790 return 1;
6791 }
6792 if(i + start >= mstruct1.size()) return -1;
6793 i2 = evalSortCompare(mstruct1[i + start], mstruct2[i + start2], parent, b_abs);
6794 if(i2 != 0) return i2;
6795 }
6796 if(mstruct1.size() - start == mstruct2.size() - start2) return 0;
6797 return -1;
6798 } else {
6799 i2 = evalSortCompare(mstruct1[start], mstruct2, parent, b_abs);
6800 if(i2 != 0) return i2;
6801 if(b_abs && start == 1 && (mstruct1[0].isMinusOne() || mstruct1[0].isOne())) return 0;
6802 return 1;
6803 }
6804 } else if(mstruct2.isMultiplication() && mstruct2.size() > 0) {
6805 size_t start = 0;
6806 while(mstruct2[start].isNumber() && mstruct2.size() > start + 1) {
6807 start++;
6808 }
6809 int i2;
6810 if(mstruct1.isMultiplication()) {
6811 return 1;
6812 } else {
6813 i2 = evalSortCompare(mstruct1, mstruct2[start], parent, b_abs);
6814 if(i2 != 0) return i2;
6815 if(b_abs && start == 1 && (mstruct2[0].isMinusOne() || mstruct2[0].isOne())) return 0;
6816 return -1;
6817 }
6818 }
6819 }
6820 if(mstruct1.type() != mstruct2.type()) {
6821 if(!parent.isMultiplication()) {
6822 if(mstruct2.isNumber()) return -1;
6823 if(mstruct1.isNumber()) return 1;
6824 }
6825 if(!parent.isMultiplication() || (!mstruct1.isNumber() && !mstruct2.isNumber())) {
6826 if(mstruct2.isPower()) {
6827 int i = evalSortCompare(mstruct1, mstruct2[0], parent, b_abs);
6828 if(i == 0) {
6829 return evalSortCompare(m_one, mstruct2[1], parent, b_abs);
6830 }
6831 return i;
6832 }
6833 if(mstruct1.isPower()) {
6834 int i = evalSortCompare(mstruct1[0], mstruct2, parent, b_abs);
6835 if(i == 0) {
6836 return evalSortCompare(mstruct1[1], m_one, parent, b_abs);
6837 }
6838 return i;
6839 }
6840 }
6841 if(mstruct2.isAborted()) return -1;
6842 if(mstruct1.isAborted()) return 1;
6843 if(mstruct2.isInverse()) return -1;
6844 if(mstruct1.isInverse()) return 1;
6845 if(mstruct2.isDivision()) return -1;
6846 if(mstruct1.isDivision()) return 1;
6847 if(mstruct2.isNegate()) return -1;
6848 if(mstruct1.isNegate()) return 1;
6849 if(mstruct2.isLogicalAnd()) return -1;
6850 if(mstruct1.isLogicalAnd()) return 1;
6851 if(mstruct2.isLogicalOr()) return -1;
6852 if(mstruct1.isLogicalOr()) return 1;
6853 if(mstruct2.isLogicalXor()) return -1;
6854 if(mstruct1.isLogicalXor()) return 1;
6855 if(mstruct2.isLogicalNot()) return -1;
6856 if(mstruct1.isLogicalNot()) return 1;
6857 if(mstruct2.isComparison()) return -1;
6858 if(mstruct1.isComparison()) return 1;
6859 if(mstruct2.isBitwiseOr()) return -1;
6860 if(mstruct1.isBitwiseOr()) return 1;
6861 if(mstruct2.isBitwiseXor()) return -1;
6862 if(mstruct1.isBitwiseXor()) return 1;
6863 if(mstruct2.isBitwiseAnd()) return -1;
6864 if(mstruct1.isBitwiseAnd()) return 1;
6865 if(mstruct2.isBitwiseNot()) return -1;
6866 if(mstruct1.isBitwiseNot()) return 1;
6867 if(mstruct2.isUndefined()) return -1;
6868 if(mstruct1.isUndefined()) return 1;
6869 if(mstruct2.isFunction()) return -1;
6870 if(mstruct1.isFunction()) return 1;
6871 if(mstruct2.isAddition()) return -1;
6872 if(mstruct1.isAddition()) return 1;
6873 if(mstruct2.isMultiplication()) return -1;
6874 if(mstruct1.isMultiplication()) return 1;
6875 if(mstruct2.isPower()) return -1;
6876 if(mstruct1.isPower()) return 1;
6877 if(mstruct2.isUnit()) return -1;
6878 if(mstruct1.isUnit()) return 1;
6879 if(mstruct2.isSymbolic()) return -1;
6880 if(mstruct1.isSymbolic()) return 1;
6881 if(mstruct2.isVariable()) return -1;
6882 if(mstruct1.isVariable()) return 1;
6883 if(mstruct2.isDateTime()) return -1;
6884 if(mstruct1.isDateTime()) return 1;
6885 if(parent.isMultiplication()) {
6886 if(mstruct2.isNumber()) return -1;
6887 if(mstruct1.isNumber()) return 1;
6888 }
6889 return -1;
6890 }
6891 switch(mstruct1.type()) {
6892 case STRUCT_NUMBER: {
6893 if(CALCULATOR->aborted()) return 0;
6894 if(b_abs) {
6895 ComparisonResult cmp = mstruct1.number().compareAbsolute(mstruct2.number());
6896 if(cmp == COMPARISON_RESULT_LESS) return -1;
6897 else if(cmp == COMPARISON_RESULT_GREATER) return 1;
6898 return 0;
6899 }
6900 if(!mstruct1.number().hasImaginaryPart() && !mstruct2.number().hasImaginaryPart()) {
6901 if(mstruct1.number().isFloatingPoint()) {
6902 if(!mstruct2.number().isFloatingPoint()) return 1;
6903 if(mstruct1.number().isInterval()) {
6904 if(!mstruct2.number().isInterval()) return 1;
6905 } else if(mstruct2.number().isInterval()) return -1;
6906 } else if(mstruct2.number().isFloatingPoint()) return -1;
6907 ComparisonResult cmp = mstruct1.number().compare(mstruct2.number());
6908 if(cmp == COMPARISON_RESULT_LESS) return -1;
6909 else if(cmp == COMPARISON_RESULT_GREATER) return 1;
6910 return 0;
6911 } else {
6912 if(!mstruct1.number().hasRealPart()) {
6913 if(mstruct2.number().hasRealPart()) {
6914 return 1;
6915 } else {
6916 ComparisonResult cmp = mstruct1.number().compareImaginaryParts(mstruct2.number());
6917 if(cmp == COMPARISON_RESULT_LESS) return -1;
6918 else if(cmp == COMPARISON_RESULT_GREATER) return 1;
6919 return 0;
6920 }
6921 } else if(mstruct2.number().hasRealPart()) {
6922 ComparisonResult cmp = mstruct1.number().compareRealParts(mstruct2.number());
6923 if(cmp == COMPARISON_RESULT_EQUAL) {
6924 cmp = mstruct1.number().compareImaginaryParts(mstruct2.number());
6925 }
6926 if(cmp == COMPARISON_RESULT_LESS) return -1;
6927 else if(cmp == COMPARISON_RESULT_GREATER) return 1;
6928 return 0;
6929 } else {
6930 return -1;
6931 }
6932 }
6933 return -1;
6934 }
6935 case STRUCT_UNIT: {
6936 if(mstruct1.unit() < mstruct2.unit()) return -1;
6937 if(mstruct1.unit() == mstruct2.unit()) return 0;
6938 return 1;
6939 }
6940 case STRUCT_SYMBOLIC: {
6941 if(mstruct1.symbol() < mstruct2.symbol()) return -1;
6942 else if(mstruct1.symbol() == mstruct2.symbol()) return 0;
6943 return 1;
6944 }
6945 case STRUCT_VARIABLE: {
6946 if(mstruct1.variable() < mstruct2.variable()) return -1;
6947 else if(mstruct1.variable() == mstruct2.variable()) return 0;
6948 return 1;
6949 }
6950 case STRUCT_FUNCTION: {
6951 if(mstruct1.function() < mstruct2.function()) return -1;
6952 if(mstruct1.function() == mstruct2.function()) {
6953 for(size_t i = 0; i < mstruct2.size(); i++) {
6954 if(i >= mstruct1.size()) {
6955 return -1;
6956 }
6957 int i2 = evalSortCompare(mstruct1[i], mstruct2[i], parent, b_abs);
6958 if(i2 != 0) return i2;
6959 }
6960 return 0;
6961 }
6962 return 1;
6963 }
6964 case STRUCT_POWER: {
6965 int i = evalSortCompare(mstruct1[0], mstruct2[0], parent, b_abs);
6966 if(i == 0) {
6967 return evalSortCompare(mstruct1[1], mstruct2[1], parent, b_abs);
6968 }
6969 return i;
6970 }
6971 default: {
6972 if(mstruct2.size() < mstruct1.size()) return -1;
6973 else if(mstruct2.size() > mstruct1.size()) return 1;
6974 int ie;
6975 for(size_t i = 0; i < mstruct1.size(); i++) {
6976 ie = evalSortCompare(mstruct1[i], mstruct2[i], parent, b_abs);
6977 if(ie != 0) {
6978 return ie;
6979 }
6980 }
6981 }
6982 }
6983 return 0;
6984 }
6985
evalSort(bool recursive,bool b_abs)6986 void MathStructure::evalSort(bool recursive, bool b_abs) {
6987 if(recursive) {
6988 for(size_t i = 0; i < SIZE; i++) {
6989 CHILD(i).evalSort(true, b_abs);
6990 }
6991 }
6992 //if(m_type != STRUCT_ADDITION && m_type != STRUCT_MULTIPLICATION && m_type != STRUCT_LOGICAL_AND && m_type != STRUCT_LOGICAL_OR && m_type != STRUCT_LOGICAL_XOR && m_type != STRUCT_BITWISE_AND && m_type != STRUCT_BITWISE_OR && m_type != STRUCT_BITWISE_XOR) return;
6993 if(m_type != STRUCT_ADDITION && m_type != STRUCT_MULTIPLICATION && m_type != STRUCT_BITWISE_AND && m_type != STRUCT_BITWISE_OR && m_type != STRUCT_BITWISE_XOR) return;
6994 if(m_type == STRUCT_ADDITION && containsType(STRUCT_DATETIME, false, true, false) > 0) return;
6995 vector<size_t> sorted;
6996 sorted.reserve(SIZE);
6997 for(size_t i = 0; i < SIZE; i++) {
6998 if(i == 0) {
6999 sorted.push_back(v_order[i]);
7000 } else {
7001 if(evalSortCompare(CHILD(i), *v_subs[sorted.back()], *this, b_abs) >= 0) {
7002 sorted.push_back(v_order[i]);
7003 } else if(sorted.size() == 1) {
7004 sorted.insert(sorted.begin(), v_order[i]);
7005 } else {
7006 for(size_t i2 = sorted.size() - 2; ; i2--) {
7007 if(evalSortCompare(CHILD(i), *v_subs[sorted[i2]], *this, b_abs) >= 0) {
7008 sorted.insert(sorted.begin() + i2 + 1, v_order[i]);
7009 break;
7010 }
7011 if(i2 == 0) {
7012 sorted.insert(sorted.begin(), v_order[i]);
7013 break;
7014 }
7015 }
7016 }
7017 }
7018 }
7019 for(size_t i2 = 0; i2 < sorted.size(); i2++) {
7020 v_order[i2] = sorted[i2];
7021 }
7022 }
7023
7024
7025