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