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 
29 /*
30 	Functions for simple handling of interval variables
31 */
32 
33 #define IS_VAR_EXP(x, ofa) ((x.isVariable() && x.variable()->isKnown() && (!ofa || x.variable()->title() == "\b")) || (x.isPower() && x[0].isVariable() && x[0].variable()->isKnown() && (!ofa || x[0].variable()->title() == "\b")))
34 
factorize_variable(MathStructure & mstruct,const MathStructure & mvar,bool deg2)35 void factorize_variable(MathStructure &mstruct, const MathStructure &mvar, bool deg2) {
36 	if(deg2) {
37 		// ax^2+bx = (sqrt(b)*x+(a/sqrt(b))/2)^2-((a/sqrt(b))/2)^2
38 		MathStructure a_struct, b_struct, mul_struct(1, 1, 0);
39 		for(size_t i2 = 0; i2 < mstruct.size();) {
40 			bool b = false;
41 			if(mstruct[i2] == mvar) {
42 				a_struct.set(1, 1, 0);
43 				b = true;
44 			} else if(mstruct[i2].isPower() && mstruct[i2][0] == mvar && mstruct[i2][1].isNumber() && mstruct[i2][1].number().isTwo()) {
45 				b_struct.set(1, 1, 0);
46 				b = true;
47 			} else if(mstruct[i2].isMultiplication()) {
48 				for(size_t i3 = 0; i3 < mstruct[i2].size(); i3++) {
49 					if(mstruct[i2][i3] == mvar) {
50 						a_struct = mstruct[i2];
51 						a_struct.delChild(i3 + 1);
52 						b = true;
53 						break;
54 					} else if(mstruct[i2][i3].isPower() && mstruct[i2][i3][0] == mvar && mstruct[i2][i3][1].isNumber() && mstruct[i2][i3][1].number().isTwo()) {
55 						b_struct = mstruct[i2];
56 						b_struct.delChild(i3 + 1);
57 						b = true;
58 						break;
59 					}
60 				}
61 			}
62 			if(b) {
63 				mstruct.delChild(i2 + 1);
64 			} else {
65 				i2++;
66 			}
67 		}
68 		if(b_struct == a_struct) {
69 			if(a_struct.isMultiplication() && a_struct.size() == 1) mul_struct = a_struct[0];
70 			else mul_struct = a_struct;
71 			a_struct.set(1, 1, 0);
72 			b_struct.set(1, 1, 0);
73 		} else if(b_struct.isMultiplication() && a_struct.isMultiplication()) {
74 			size_t i3 = 0;
75 			for(size_t i = 0; i < a_struct.size();) {
76 				bool b = false;
77 				for(size_t i2 = i3; i2 < b_struct.size(); i2++) {
78 					if(a_struct[i] == b_struct[i2]) {
79 						i3 = i2;
80 						if(mul_struct.isOne()) mul_struct = a_struct[i];
81 						else mul_struct.multiply(a_struct[i], true);
82 						a_struct.delChild(i + 1);
83 						b_struct.delChild(i2 + 1);
84 						b = true;
85 						break;
86 					}
87 				}
88 				if(!b) i++;
89 			}
90 		}
91 		if(a_struct.isMultiplication() && a_struct.size() == 0) a_struct.set(1, 1, 0);
92 		else if(a_struct.isMultiplication() && a_struct.size() == 1) a_struct.setToChild(1);
93 		if(b_struct.isMultiplication() && b_struct.size() == 0) b_struct.set(1, 1, 0);
94 		else if(b_struct.isMultiplication() && b_struct.size() == 1) b_struct.setToChild(1);
95 		if(!b_struct.isOne()) {
96 			b_struct.raise(nr_half);
97 			a_struct.divide(b_struct);
98 		}
99 		a_struct.multiply(nr_half);
100 		if(b_struct.isOne()) b_struct = mvar;
101 		else b_struct *= mvar;
102 		b_struct += a_struct;
103 		b_struct.raise(nr_two);
104 		a_struct.raise(nr_two);
105 		a_struct.negate();
106 		b_struct += a_struct;
107 		if(!mul_struct.isOne()) b_struct *= mul_struct;
108 		if(mstruct.size() == 0) mstruct = b_struct;
109 		else mstruct.addChild(b_struct);
110 	} else {
111 		vector<MathStructure*> left_structs;
112 		for(size_t i2 = 0; i2 < mstruct.size();) {
113 			bool b = false;
114 			if(mstruct[i2] == mvar) {
115 				mstruct[i2].set(1, 1, 0, true);
116 				b = true;
117 			} else if(mstruct[i2].isMultiplication()) {
118 				for(size_t i3 = 0; i3 < mstruct[i2].size(); i3++) {
119 					if(mstruct[i2][i3] == mvar) {
120 						mstruct[i2].delChild(i3 + 1, true);
121 						b = true;
122 						break;
123 					}
124 				}
125 			}
126 			if(b) {
127 				i2++;
128 			} else {
129 				mstruct[i2].ref();
130 				left_structs.push_back(&mstruct[i2]);
131 				mstruct.delChild(i2 + 1);
132 			}
133 		}
134 		mstruct.multiply(mvar);
135 		for(size_t i = 0; i < left_structs.size(); i++) {
136 			mstruct.add_nocopy(left_structs[i], true);
137 			mstruct.evalSort(false);
138 		}
139 	}
140 }
var_contains_interval(const MathStructure & mstruct)141 bool var_contains_interval(const MathStructure &mstruct) {
142 	if(mstruct.isNumber()) return mstruct.number().isInterval();
143 	if(mstruct.isFunction() && (mstruct.function()->id() == FUNCTION_ID_INTERVAL || mstruct.function()->id() == FUNCTION_ID_UNCERTAINTY)) return true;
144 	if(mstruct.isVariable() && mstruct.variable()->isKnown()) return var_contains_interval(((KnownVariable*) mstruct.variable())->get());
145 	for(size_t i = 0; i < mstruct.size(); i++) {
146 		if(var_contains_interval(mstruct[i])) return true;
147 	}
148 	return false;
149 }
150 
factorize_variables(MathStructure & mstruct,const EvaluationOptions & eo,bool ofa=false)151 bool factorize_variables(MathStructure &mstruct, const EvaluationOptions &eo, bool ofa = false) {
152 	bool b = false;
153 	if(mstruct.type() == STRUCT_ADDITION) {
154 		vector<MathStructure> variables;
155 		vector<size_t> variable_count;
156 		vector<int> term_sgn;
157 		vector<bool> term_deg2;
158 		for(size_t i = 0; i < mstruct.size(); i++) {
159 			if(CALCULATOR->aborted()) break;
160 			if(mstruct[i].isMultiplication()) {
161 				for(size_t i2 = 0; i2 < mstruct[i].size(); i2++) {
162 					if(CALCULATOR->aborted()) break;
163 					if(IS_VAR_EXP(mstruct[i][i2], ofa)) {
164 						bool b_found = false;
165 						for(size_t i3 = 0; i3 < variables.size(); i3++) {
166 							if(variables[i3] == mstruct[i][i2]) {
167 								variable_count[i3]++;
168 								b_found = true;
169 								if(term_sgn[i3] == 1 && !mstruct[i].representsNonNegative(true)) term_sgn[i3] = 0;
170 								else if(term_sgn[i3] == -1 && !mstruct[i].representsNonPositive(true)) term_sgn[i3] = 0;
171 								break;
172 							}
173 						}
174 						if(!b_found) {
175 							variables.push_back(mstruct[i][i2]);
176 							variable_count.push_back(1);
177 							term_deg2.push_back(false);
178 							if(mstruct[i].representsNonNegative(true)) term_sgn.push_back(1);
179 							else if(mstruct[i].representsNonPositive(true)) term_sgn.push_back(-1);
180 							else term_sgn.push_back(0);
181 						}
182 					}
183 				}
184 			} else if(IS_VAR_EXP(mstruct[i], ofa)) {
185 				bool b_found = false;
186 				for(size_t i3 = 0; i3 < variables.size(); i3++) {
187 					if(variables[i3] == mstruct[i]) {
188 						variable_count[i3]++;
189 						b_found = true;
190 						if(term_sgn[i3] == 1 && !mstruct[i].representsNonNegative(true)) term_sgn[i3] = 0;
191 						else if(term_sgn[i3] == -1 && !mstruct[i].representsNonPositive(true)) term_sgn[i3] = 0;
192 						break;
193 					}
194 				}
195 				if(!b_found) {
196 					variables.push_back(mstruct[i]);
197 					variable_count.push_back(1);
198 					term_deg2.push_back(false);
199 					if(mstruct[i].representsNonNegative(true)) term_sgn.push_back(1);
200 					else if(mstruct[i].representsNonPositive(true)) term_sgn.push_back(-1);
201 					else term_sgn.push_back(0);
202 				}
203 			}
204 		}
205 		for(size_t i = 0; i < variables.size();) {
206 			bool b_erase = false;
207 			if(!var_contains_interval(variables[i])) {
208 				b_erase = true;
209 			} else if(variable_count[i] == 1 || term_sgn[i] != 0) {
210 				b_erase = true;
211 				if(!variables[i].isPower() || (variables[i][1].isNumber() && variables[i][1].number().isTwo())) {
212 					for(size_t i2 = i + 1; i2 < variables.size(); i2++) {
213 						if((variables[i].isPower() && !variables[i2].isPower() && variables[i][0] == variables[i2])|| (!variables[i].isPower() && variables[i2].isPower() && variables[i2][0] == variables[i] && variables[i2][1].isNumber() && variables[i2][1].number().isTwo())) {
214 							bool b_erase2 = false;
215 							if(variable_count[i2] == 1) {
216 								if(term_sgn[i] == 0 || term_sgn[i2] != term_sgn[i]) {
217 									if(variable_count[i] == 1) {
218 										term_deg2[i] = true;
219 										variable_count[i] = 2;
220 										term_sgn[i] = 0;
221 										if(variables[i].isPower()) variables[i].setToChild(1);
222 									} else {
223 										term_sgn[i] = 0;
224 									}
225 									b_erase = false;
226 								}
227 								b_erase2 = true;
228 							} else if(term_sgn[i2] != 0) {
229 								if(term_sgn[i] == 0 || term_sgn[i2] != term_sgn[i]) {
230 									if(variable_count[i] != 1) {
231 										term_sgn[i] = 0;
232 										b_erase = false;
233 									}
234 									term_sgn[i2] = 0;
235 								} else {
236 									b_erase2 = true;
237 								}
238 							}
239 							if(b_erase2) {
240 								variable_count.erase(variable_count.begin() + i2);
241 								variables.erase(variables.begin() + i2);
242 								term_deg2.erase(term_deg2.begin() + i2);
243 								term_sgn.erase(term_sgn.begin() + i2);
244 							}
245 							break;
246 						}
247 					}
248 				}
249 			}
250 			if(b_erase) {
251 				variable_count.erase(variable_count.begin() + i);
252 				variables.erase(variables.begin() + i);
253 				term_deg2.erase(term_deg2.begin() + i);
254 				term_sgn.erase(term_sgn.begin() + i);
255 			} else if(variable_count[i] == mstruct.size()) {
256 				factorize_variable(mstruct, variables[i], term_deg2[i]);
257 				if(CALCULATOR->aborted()) return true;
258 				factorize_variables(mstruct, eo, ofa);
259 				return true;
260 			} else {
261 				i++;
262 			}
263 		}
264 		if(variables.size() == 1) {
265 			factorize_variable(mstruct, variables[0], term_deg2[0]);
266 			if(CALCULATOR->aborted()) return true;
267 			factorize_variables(mstruct, eo, ofa);
268 			return true;
269 		}
270 		Number uncertainty;
271 		size_t u_index = 0;
272 		for(size_t i = 0; i < variables.size(); i++) {
273 			const MathStructure *v_ms;
274 			Number nr;
275 			if(variables[i].isPower()) v_ms = &((KnownVariable*) variables[i][0].variable())->get();
276 			else v_ms = &((KnownVariable*) variables[i].variable())->get();
277 			if(v_ms->isNumber()) nr = v_ms->number();
278 			else if(v_ms->isMultiplication() && v_ms->size() > 0 && (*v_ms)[0].isNumber()) nr = (v_ms)[0].number();
279 			else {
280 				MathStructure mtest(*v_ms);
281 				mtest.unformat(eo);
282 				mtest.calculatesub(eo, eo, true);
283 				if(mtest.isNumber()) nr = mtest.number();
284 				else if(mtest.isMultiplication() && mtest.size() > 0 && mtest[0].isNumber()) nr = mtest[0].number();
285 			}
286 			if(nr.isInterval()) {
287 				Number u_candidate(nr.uncertainty());
288 				if(variables[i].isPower() && variables[i][1].isNumber() && variables[i][1].number().isReal()) u_candidate.raise(variables[i][1].number());
289 				u_candidate.multiply(variable_count[i]);
290 				if(u_candidate.isGreaterThan(uncertainty)) {
291 					uncertainty = u_candidate;
292 					u_index = i;
293 				}
294 			}
295 		}
296 		if(!uncertainty.isZero()) {
297 			factorize_variable(mstruct, variables[u_index], term_deg2[u_index]);
298 			if(CALCULATOR->aborted()) return true;
299 			factorize_variables(mstruct, eo, ofa);
300 			return true;
301 		}
302 
303 	}
304 	for(size_t i = 0; i < mstruct.size(); i++) {
305 		if(factorize_variables(mstruct[i], eo, ofa)) {
306 			mstruct.childUpdated(i + 1);
307 			b = true;
308 		}
309 		if(CALCULATOR->aborted()) return b;
310 	}
311 	return b;
312 }
contains_duplicate_interval_variables_eq(const MathStructure & mstruct,const MathStructure & xvar,vector<KnownVariable * > & vars)313 bool contains_duplicate_interval_variables_eq(const MathStructure &mstruct, const MathStructure &xvar, vector<KnownVariable*> &vars) {
314 	if(mstruct.isVariable() && mstruct.variable()->isKnown() && ((KnownVariable*) mstruct.variable())->get().containsInterval(false, true, false, false)) {
315 		KnownVariable *v = (KnownVariable*) mstruct.variable();
316 		for(size_t i = 0; i < vars.size(); i++) {
317 			if(vars[i] == v) {
318 				return true;
319 			}
320 		}
321 		vars.push_back(v);
322 	}
323 	for(size_t i = 0; i < mstruct.size(); i++) {
324 		if(contains_duplicate_interval_variables_eq(mstruct[i], xvar, vars)) return true;
325 	}
326 	return false;
327 }
fix_eqs(MathStructure & m,const EvaluationOptions & eo)328 bool fix_eqs(MathStructure &m, const EvaluationOptions &eo) {
329 	for(size_t i = 0; i < m.size(); i++) {
330 		if(fix_eqs(m[i], eo)) m.childUpdated(i + 1);
331 	}
332 	if(m.isComparison()) {
333 		if(CALCULATOR->aborted()) return false;
334 		const MathStructure *x_var;
335 		if(eo.isolate_var && m.contains(*eo.isolate_var)) x_var = eo.isolate_var;
336 		else x_var = &m.find_x_var();
337 		if(!x_var->isUndefined()) {
338 			vector<KnownVariable*> vars;
339 			if(contains_duplicate_interval_variables_eq(m, *x_var, vars)) {
340 				if(!m[0].contains(*x_var)) {
341 					m.swapChildren(1, 2);
342 				} else if(m[0].isAddition()) {
343 					for(size_t i = 0; i < m[0].size();) {
344 						if(!m[0][i].contains(*x_var)) {
345 							m[0][i].calculateNegate(eo);
346 							m[0][i].ref();
347 							m[1].add_nocopy(&m[0][i], true);
348 							m[1].calculateAddLast(eo);
349 							m[0].delChild(i + 1);
350 						} else {
351 							i++;
352 						}
353 					}
354 					if(m[0].size() == 1) m[0].setToChild(1, true);
355 					else if(m[0].size() == 0) m[0].clear(true);
356 					m.childrenUpdated();
357 				}
358 				if(m[1].isAddition()) {
359 					for(size_t i = 0; i < m[1].size();) {
360 						if(m[1][i].contains(*x_var)) {
361 							m[1][i].calculateNegate(eo);
362 							m[1][i].ref();
363 							m[0].add_nocopy(&m[1][i], true);
364 							m[0].calculateAddLast(eo);
365 							m[1].delChild(i + 1);
366 						} else {
367 							i++;
368 						}
369 					}
370 					if(m[1].size() == 1) m[1].setToChild(1, true);
371 					else if(m[1].size() == 0) m[1].clear(true);
372 					m.childrenUpdated();
373 				} else if(m[1].contains(*x_var)) {
374 					m[0].calculateSubtract(m[1], eo);
375 					m[1].clear(true);
376 				}
377 				vars.clear();
378 				if(m[0].containsType(STRUCT_ADDITION) && contains_duplicate_interval_variables_eq(m[0], *x_var, vars)) m[0].factorize(eo, false, false, 0, false, 1, NULL, m_undefined, false, false, 3);
379 				return true;
380 			}
381 		}
382 	}
383 	return false;
384 }
385 // end functions for simple handling of interval variables
386 
387 
388 /*
389 
390 	Functions for handling of interval variables using interval arithmetic. Calculates the derivative of the expression for each interval variable, searches 	points where the derivative is zero, and calculates the epxression separately for approriate subintervals.
391 
392 */
393 
find_interval_variables(const MathStructure & mstruct,vector<KnownVariable * > & vars,vector<int> & v_count,vector<int> & v_prec)394 void find_interval_variables(const MathStructure &mstruct, vector<KnownVariable*> &vars, vector<int> &v_count, vector<int> &v_prec) {
395 	if(mstruct.isVariable() && mstruct.variable()->isKnown()) {
396 		KnownVariable *v = (KnownVariable*) mstruct.variable();
397 		int var_prec = PRECISION + 11;
398 		const MathStructure &mv = v->get();
399 		for(size_t i = 0; i < vars.size(); i++) {
400 			if(vars[i] == v) {
401 				v_count[i]++;
402 				return;
403 			}
404 		}
405 		if(mv.isNumber()) {
406 			if(mv.number().isInterval()) var_prec = mv.number().precision(1);
407 			else if(CALCULATOR->usesIntervalArithmetic() && mv.number().precision() >= 0) var_prec = mv.number().precision();
408 		} else if(mv.isMultiplication()) {
409 			for(size_t i = 0; i < mv.size(); i++) {
410 				if(mv[i].isNumber()) {
411 					if(mv[i].number().isInterval()) {var_prec = mv[i].number().precision(1); break;}
412 					else if(mv[i].number().precision() >= 0) {var_prec = mv[i].number().precision(); break;}
413 				}
414 			}
415 		}
416 		if(var_prec <= PRECISION + 10) {
417 			bool b = false;
418 			for(size_t i = 0; i < v_prec.size(); i++) {
419 				if(var_prec < v_prec[i]) {
420 					v_prec.insert(v_prec.begin() + i, var_prec);
421 					v_count.insert(v_count.begin() + i, 1);
422 					vars.insert(vars.begin() + i, v);
423 					b = true;
424 					break;
425 				}
426 			}
427 			if(!b) {
428 				v_prec.push_back(var_prec);
429 				v_count.push_back(1);
430 				vars.push_back(v);
431 			}
432 		}
433 	}
434 	for(size_t i = 0; i < mstruct.size(); i++) {
435 		find_interval_variables(mstruct[i], vars, v_count, v_prec);
436 	}
437 }
contains_not_nonzero(MathStructure & m)438 bool contains_not_nonzero(MathStructure &m) {
439 	if(m.isNumber() && !m.number().isNonZero()) {
440 		return true;
441 	} else if(m.isMultiplication()) {
442 		for(size_t i = 0; i < m.size(); i++) {
443 			if(contains_not_nonzero(m[i])) return true;
444 		}
445 	}
446 	return false;
447 }
contains_undefined(MathStructure & m,const EvaluationOptions & eo=default_evaluation_options,bool calc=false,const MathStructure & x_var=m_zero,const MathStructure & m_intval=nr_zero)448 bool contains_undefined(MathStructure &m, const EvaluationOptions &eo = default_evaluation_options, bool calc = false, const MathStructure &x_var = m_zero, const MathStructure &m_intval = nr_zero) {
449 	if(m.isPower() && (m[1].representsNegative() || (m[1].isNumber() && !m[1].number().isNonNegative()))) {
450 		if(calc) {
451 			m[0].replace(x_var, m_intval, true);
452 			m[0].calculatesub(eo, eo, true);
453 		}
454 		if(contains_not_nonzero(m[0])) return true;
455 	}
456 	for(size_t i = 0; i < m.size(); i++) {
457 		if(contains_undefined(m[i], eo, calc, x_var, m_intval)) return true;
458 	}
459 	return false;
460 }
461 
462 // search for values where the expression is non-zero, using intervals of diminishing width
find_interval_zeroes(const MathStructure & mstruct,MathStructure & malts,const MathStructure & mvar,const Number & nr_intval,const EvaluationOptions & eo,int depth,const Number & nr_prec,int orig_prec=0,int is_real=-1,int undef_depth=0)463 bool find_interval_zeroes(const MathStructure &mstruct, MathStructure &malts, const MathStructure &mvar, const Number &nr_intval, const EvaluationOptions &eo, int depth, const Number &nr_prec, int orig_prec = 0, int is_real = -1, int undef_depth = 0) {
464 	if(CALCULATOR->aborted()) return false;
465 	if(depth == 0) orig_prec = nr_intval.precision(1);
466 	MathStructure mtest(mstruct);
467 	mtest.replace(mvar, nr_intval);
468 	mtest.eval(eo);
469 	if(is_real < 0) is_real = mtest.representsNonComplex(true);
470 	ComparisonResult cmp;
471 	if(is_real == 0) {
472 		MathStructure m_re(CALCULATOR->getFunctionById(FUNCTION_ID_RE), &mtest, NULL);
473 		m_re.calculateFunctions(eo);
474 		cmp = m_re.compare(m_zero);
475 		MathStructure m_im(CALCULATOR->getFunctionById(FUNCTION_ID_IM), &mtest, NULL);
476 		m_im.calculateFunctions(eo);
477 		ComparisonResult cmp2 = m_im.compare(m_zero);
478 		if(COMPARISON_IS_NOT_EQUAL(cmp) || cmp2 == COMPARISON_RESULT_EQUAL || cmp == COMPARISON_RESULT_UNKNOWN) cmp = cmp2;
479 	} else {
480 		cmp = mtest.compare(m_zero);
481 	}
482 	if(COMPARISON_IS_NOT_EQUAL(cmp)) {
483 		return true;
484 	} else if(cmp != COMPARISON_RESULT_UNKNOWN || (undef_depth <= 5 && contains_undefined(mtest))) {
485 		if(cmp == COMPARISON_RESULT_EQUAL || (nr_intval.precision(1) > (orig_prec > PRECISION ? orig_prec + 5 : PRECISION + 5) || (!nr_intval.isNonZero() && nr_intval.uncertainty().isLessThan(nr_prec)))) {
486 			if(cmp == COMPARISON_RESULT_EQUAL && depth <= 3) return false;
487 			if(malts.size() > 0 && (cmp = malts.last().compare(nr_intval)) != COMPARISON_RESULT_UNKNOWN && COMPARISON_MIGHT_BE_EQUAL(cmp)) {
488 				malts.last().number().setInterval(malts.last().number(), nr_intval);
489 				if(malts.last().number().precision(1) < (orig_prec > PRECISION ? orig_prec + 3 : PRECISION + 3)) {
490 					return false;
491 				}
492 			} else {
493 				malts.addChild(nr_intval);
494 			}
495 			return true;
496 		}
497 		vector<Number> splits;
498 		nr_intval.splitInterval(2, splits);
499 		for(size_t i = 0; i < splits.size(); i++) {
500 			if(!find_interval_zeroes(mstruct, malts, mvar, splits[i], eo, depth + 1, nr_prec, orig_prec, is_real, cmp == COMPARISON_RESULT_UNKNOWN ? undef_depth + 1 : 0)) return false;
501 		}
502 		return true;
503 	}
504 	return false;
505 }
contains_interval_variable(const MathStructure & m,int i_type=0)506 bool contains_interval_variable(const MathStructure &m, int i_type = 0) {
507 	if(i_type == 0 && m.isVariable() && m.containsInterval(true, true, false, 1, false)) return true;
508 	else if(i_type == 1 && m.containsInterval(true, false, false, 1, true)) return true;
509 	else if(i_type == 2 && m.containsInterval(true, true, false, 1, true)) return true;
510 	for(size_t i = 0; i < m.size(); i++) {
511 		if(contains_interval_variable(m[i])) return true;
512 	}
513 	return false;
514 }
calculate_differentiable_functions(MathStructure & m,const EvaluationOptions & eo,bool recursive=true,bool do_unformat=true)515 bool calculate_differentiable_functions(MathStructure &m, const EvaluationOptions &eo, bool recursive = true, bool do_unformat = true) {
516 	if(m.isFunction() && m.function() != eo.protected_function && function_differentiable(m.function())) {
517 		return m.calculateFunctions(eo, recursive, do_unformat);
518 	}
519 	bool b = false;
520 	if(recursive) {
521 		for(size_t i = 0; i < m.size(); i++) {
522 			if(CALCULATOR->aborted()) break;
523 			if(calculate_differentiable_functions(m[i], eo, recursive, do_unformat)) {
524 				m.childUpdated(i + 1);
525 				b = true;
526 			}
527 		}
528 	}
529 	return b;
530 }
calculate_nondifferentiable_functions(MathStructure & m,const EvaluationOptions & eo,bool recursive,bool do_unformat,int i_type)531 bool calculate_nondifferentiable_functions(MathStructure &m, const EvaluationOptions &eo, bool recursive, bool do_unformat, int i_type) {
532 	if(m.isFunction() && m.function() != eo.protected_function) {
533 		if((i_type <= 0 && !function_differentiable(m.function())) || (i_type >= 0 && !contains_interval_variable(m, i_type))) {
534 			if(m.calculateFunctions(eo, false, do_unformat)) {
535 				if(recursive) calculate_nondifferentiable_functions(m, eo, recursive, do_unformat, i_type);
536 				return true;
537 			}
538 		} else if(m.function()->id() == FUNCTION_ID_ABS && m.size() == 1) {
539 			EvaluationOptions eo3 = eo;
540 			eo3.split_squares = false;
541 			eo3.assume_denominators_nonzero = false;
542 			if(eo.approximation == APPROXIMATION_APPROXIMATE && !m.containsUnknowns()) eo3.approximation = APPROXIMATION_EXACT_VARIABLES;
543 			else eo3.approximation = APPROXIMATION_EXACT;
544 			m[0].calculatesub(eo3, eo);
545 			m.childUpdated(1);
546 			if(m[0].representsNegative(true)) {
547 				m.setToChild(1);
548 				m.negate();
549 				if(recursive) calculate_nondifferentiable_functions(m, eo, recursive, do_unformat, i_type);
550 				return true;
551 			}
552 			if(m[0].representsNonNegative(true)) {
553 				m.setToChild(1);
554 				if(recursive) calculate_nondifferentiable_functions(m, eo, recursive, do_unformat, i_type);
555 				return true;
556 			}
557 			if(m[0].isMultiplication()) {
558 				m.setToChild(1);
559 				for(size_t i = 0; i < m.size(); i++) {
560 					m[i].transformById(FUNCTION_ID_ABS);
561 				}
562 				m.childrenUpdated();
563 				if(recursive) calculate_nondifferentiable_functions(m, eo, recursive, do_unformat, i_type);
564 				return true;
565 			}
566 			if(eo.approximation != APPROXIMATION_EXACT) {
567 				eo3.approximation = APPROXIMATION_APPROXIMATE;
568 				MathStructure mtest(m[0]);
569 				mtest.calculatesub(eo3, eo);
570 				if(mtest.representsNegative(true)) {
571 					m.setToChild(1);
572 					m.negate();
573 					if(recursive) calculate_nondifferentiable_functions(m, eo, recursive, do_unformat, i_type);
574 					return true;
575 				}
576 				if(mtest.representsNonNegative(true)) {
577 					m.setToChild(1);
578 					if(recursive) calculate_nondifferentiable_functions(m, eo, recursive, do_unformat, i_type);
579 					return true;
580 				}
581 			}
582 		}
583 	}
584 	bool b = false;
585 	if(recursive) {
586 		for(size_t i = 0; i < m.size(); i++) {
587 			if(CALCULATOR->aborted()) break;
588 			if(calculate_nondifferentiable_functions(m[i], eo, recursive, do_unformat, i_type)) {
589 				m.childUpdated(i + 1);
590 				b = true;
591 			}
592 		}
593 	}
594 	return b;
595 }
596 
remove_nonzero_mul(MathStructure & msolve,const MathStructure & u_var,const EvaluationOptions & eo)597 void remove_nonzero_mul(MathStructure &msolve, const MathStructure &u_var, const EvaluationOptions &eo) {
598 	if(!msolve.isMultiplication()) return;
599 	for(size_t i = 0; i < msolve.size();) {
600 		if(!msolve[i].contains(u_var, true)) {
601 			msolve[i].eval(eo);
602 			if(msolve[i].representsNonZero(true)) {
603 				if(msolve.size() == 2) {
604 					msolve.delChild(i + 1, true);
605 					break;
606 				}
607 				msolve.delChild(i + 1, true);
608 			} else {
609 				remove_nonzero_mul(msolve[i], u_var, eo);
610 				i++;
611 			}
612 		} else {
613 			remove_nonzero_mul(msolve[i], u_var, eo);
614 			i++;
615 		}
616 	}
617 }
618 
solve_intervals2(MathStructure & mstruct,vector<KnownVariable * > vars,const EvaluationOptions & eo_pre)619 void solve_intervals2(MathStructure &mstruct, vector<KnownVariable*> vars, const EvaluationOptions &eo_pre) {
620 	if(vars.size() > 0) {
621 		EvaluationOptions eo = eo_pre;
622 		eo.approximation = APPROXIMATION_EXACT_VARIABLES;
623 		eo.expand = false;
624 		if(eo.calculate_functions) calculate_differentiable_functions(mstruct, eo);
625 		KnownVariable *v = vars[0];
626 		vars.erase(vars.begin());
627 		UnknownVariable *u_var = new UnknownVariable("", "u");
628 		Number nr_intval;
629 		MathStructure mvar(u_var);
630 		const MathStructure &mv = v->get();
631 		MathStructure mmul(1, 1, 0);
632 		if(mv.isMultiplication()) {
633 			for(size_t i = 0; i < mv.size(); i++) {
634 				if(mv[i].isNumber() && mv[i].number().isInterval()) {
635 					mmul = mv;
636 					mmul.unformat(eo);
637 					mmul.delChild(i + 1, true);
638 					mvar.multiply(mmul);
639 					nr_intval = mv[i].number();
640 					u_var->setInterval(nr_intval);
641 					break;
642 				}
643 			}
644 		} else {
645 			nr_intval = mv.number();
646 			u_var->setInterval(mv);
647 		}
648 		MathStructure msolve(mstruct);
649 		msolve.replace(v, mvar);
650 		bool b = true;
651 		CALCULATOR->beginTemporaryStopMessages();
652 
653 		if(!msolve.differentiate(u_var, eo) || msolve.countTotalChildren(false) > 10000 || contains_diff_for(msolve, u_var) || CALCULATOR->aborted()) {
654 			b = false;
655 		}
656 
657 		MathStructure malts;
658 		malts.clearVector();
659 		if(b) {
660 			eo.keep_zero_units = false;
661 			eo.approximation = APPROXIMATION_APPROXIMATE;
662 			eo.expand = eo_pre.expand;
663 			// test if derivative is non-zero, replacing each occurrence of the variable with independent intervals
664 			MathStructure mtest(msolve);
665 			mtest.replace(u_var, nr_intval);
666 			mtest.eval(eo);
667 			if(mtest.countTotalChildren(false) < 100) {
668 				if(mtest.representsNonComplex(true)) {
669 					ComparisonResult cmp = mtest.compare(m_zero);
670 					if(!COMPARISON_IS_EQUAL_OR_GREATER(cmp) && !COMPARISON_IS_EQUAL_OR_LESS(cmp)) b = false;
671 				} else {
672 					MathStructure m_re(CALCULATOR->getFunctionById(FUNCTION_ID_RE), &mtest, NULL);
673 					m_re.calculateFunctions(eo);
674 					ComparisonResult cmp = m_re.compare(m_zero);
675 					if(!COMPARISON_IS_EQUAL_OR_GREATER(cmp) && !COMPARISON_IS_EQUAL_OR_LESS(cmp)) {
676 						b = false;
677 					} else {
678 						MathStructure m_im(CALCULATOR->getFunctionById(FUNCTION_ID_IM), &mtest, NULL);
679 						m_im.calculateFunctions(eo);
680 						ComparisonResult cmp = m_im.compare(m_zero);
681 						if(!COMPARISON_IS_EQUAL_OR_GREATER(cmp) && !COMPARISON_IS_EQUAL_OR_LESS(cmp)) b = false;
682 					}
683 				}
684 			} else {
685 				b = false;
686 			}
687 			eo.expand = false;
688 			eo.approximation = APPROXIMATION_EXACT_VARIABLES;
689 			if(!b) {
690 				b = true;
691 				msolve.calculatesub(eo, eo, true);
692 				eo.approximation = APPROXIMATION_APPROXIMATE;
693 				eo.expand = eo_pre.expand;
694 				msolve.factorize(eo, false, false, 0, false, true, NULL, m_undefined, false, false, 1);
695 				remove_nonzero_mul(msolve, u_var, eo);
696 				if(msolve.isZero()) {
697 				} else if(contains_undefined(msolve) || msolve.countTotalChildren(false) > 1000 || msolve.containsInterval(true, true, false, 1, true)) {
698 					b = false;
699 				} else {
700 					MathStructure mtest(mstruct);
701 					mtest.replace(v, u_var);
702 					mtest.calculatesub(eo, eo, true);
703 					if(contains_undefined(mtest, eo, true, u_var, mv)) {
704 						b = false;
705 					} else {
706 						Number nr_prec(1, 1, -(PRECISION + 10));
707 						nr_prec *= nr_intval.uncertainty();
708 						// search for values where derivative is non-zero
709 						b = find_interval_zeroes(msolve, malts, u_var, nr_intval, eo, 0, nr_prec);
710 					}
711 				}
712 				eo.expand = false;
713 				eo.approximation = APPROXIMATION_EXACT_VARIABLES;
714 			}
715 			eo.keep_zero_units = eo_pre.keep_zero_units;
716 		}
717 		CALCULATOR->endTemporaryStopMessages();
718 		CALCULATOR->beginTemporaryStopMessages();
719 		if(b) {
720 			malts.addChild(nr_intval.lowerEndPoint());
721 			malts.addChild(nr_intval.upperEndPoint());
722 			MathStructure mnew;
723 			for(size_t i = 0; i < malts.size(); i++) {
724 				MathStructure mlim(mstruct);
725 				if(!mmul.isOne()) malts[i] *= mmul;
726 				mlim.replace(v, malts[i]);
727 				mlim.calculatesub(eo, eo, true);
728 				vector<KnownVariable*> vars2 = vars;
729 				solve_intervals2(mlim, vars2, eo_pre);
730 				if(i == 0) {
731 					mnew = mlim;
732 				} else {
733 					MathStructure mlim1(mnew);
734 					if(!create_interval(mnew, mlim1, mlim)) {
735 						eo.approximation = APPROXIMATION_APPROXIMATE;
736 						eo.expand = eo_pre.expand;
737 						mlim.eval(eo);
738 						if(!create_interval(mnew, mlim1, mlim)) {
739 							mlim1.eval(eo);
740 							eo.expand = false;
741 							eo.approximation = APPROXIMATION_EXACT_VARIABLES;
742 							if(!create_interval(mnew, mlim1, mlim)) {
743 								b = false;
744 								break;
745 							}
746 						}
747 					}
748 				}
749 			}
750 			if(b) mstruct = mnew;
751 		}
752 		CALCULATOR->endTemporaryStopMessages(b);
753 		if(!b) {
754 			CALCULATOR->error(false, MESSAGE_CATEGORY_WIDE_INTERVAL, _("Interval potentially calculated wide."), NULL);
755 			mstruct.replace(v, v->get());
756 			mstruct.unformat(eo_pre);
757 			solve_intervals2(mstruct, vars, eo_pre);
758 		}
759 		u_var->destroy();
760 	}
761 }
fix_find_interval_variable(MathStructure & mstruct)762 KnownVariable *fix_find_interval_variable(MathStructure &mstruct) {
763 	if(mstruct.isVariable() && mstruct.variable()->isKnown()) {
764 		const MathStructure &m = ((KnownVariable*) mstruct.variable())->get();
765 		if(contains_interval_variable(m)) return (KnownVariable*) mstruct.variable();
766 	}
767 	for(size_t i = 0; i < mstruct.size(); i++) {
768 		KnownVariable *v = fix_find_interval_variable(mstruct[i]);
769 		if(v) return v;
770 	}
771 	return NULL;
772 }
fix_find_interval_variable2(MathStructure & mstruct)773 KnownVariable *fix_find_interval_variable2(MathStructure &mstruct) {
774 	if(mstruct.isVariable() && mstruct.variable()->isKnown()) {
775 		const MathStructure &m = ((KnownVariable*) mstruct.variable())->get();
776 		if(m.isNumber()) return NULL;
777 		if(m.isMultiplication()) {
778 			bool b_intfound = false;;
779 			for(size_t i = 0; i < m.size(); i++) {
780 				if(m[i].containsInterval(true, false, false, 1)) {
781 					if(b_intfound || !m[i].isNumber()) return (KnownVariable*) mstruct.variable();
782 					b_intfound = true;
783 				}
784 			}
785 		} else if(m.containsInterval(true, false, false, 1)) {
786 			return (KnownVariable*) mstruct.variable();
787 		}
788 	}
789 	for(size_t i = 0; i < mstruct.size(); i++) {
790 		KnownVariable *v = fix_find_interval_variable2(mstruct[i]);
791 		if(v) return v;
792 	}
793 	return NULL;
794 }
replace_intervals(MathStructure & m)795 bool replace_intervals(MathStructure &m) {
796 	if(m.isNumber()) {
797 		int var_prec = 0;
798 		if(m.number().isInterval()) var_prec = m.number().precision(1);
799 		else if(CALCULATOR->usesIntervalArithmetic() && m.number().precision() >= 0) var_prec = m.number().precision();
800 		if(var_prec <= PRECISION + 10) {
801 			Variable *v = new KnownVariable("", format_and_print(m), m);
802 			m.set(v, true);
803 			v->destroy();
804 		}
805 	}
806 	bool b = false;
807 	for(size_t i = 0; i < m.size(); i++) {
808 		if(replace_intervals(m[i])) {
809 			m.childUpdated(i + 1);
810 			b = true;
811 		}
812 	}
813 	return b;
814 }
fix_interval_variable(KnownVariable * v,MathStructure & mvar)815 void fix_interval_variable(KnownVariable *v, MathStructure &mvar) {
816 	mvar = v->get();
817 	replace_intervals(mvar);
818 }
819 
solve_intervals(MathStructure & mstruct,const EvaluationOptions & eo,const EvaluationOptions & feo)820 void solve_intervals(MathStructure &mstruct, const EvaluationOptions &eo, const EvaluationOptions &feo) {
821 	bool b = false;
822 	while(true) {
823 		KnownVariable *v = fix_find_interval_variable(mstruct);
824 		if(!v) break;
825 		b = true;
826 		MathStructure mvar;
827 		fix_interval_variable(v, mvar);
828 		mstruct.replace(v, mvar);
829 	}
830 	while(true) {
831 		KnownVariable *v = fix_find_interval_variable2(mstruct);
832 		if(!v) break;
833 		b = true;
834 		MathStructure mvar;
835 		fix_interval_variable(v, mvar);
836 		mstruct.replace(v, mvar);
837 	}
838 	if(b) {
839 		mstruct.unformat(eo);
840 		EvaluationOptions eo2 = eo;
841 		eo2.expand = false;
842 		mstruct.calculatesub(eo2, feo, true);
843 	}
844 	vector<KnownVariable*> vars; vector<int> v_count; vector<int> v_prec;
845 	find_interval_variables(mstruct, vars, v_count, v_prec);
846 	for(size_t i = 0; i < v_count.size();) {
847 		if(v_count[i] < 2 || (feo.approximation == APPROXIMATION_EXACT && vars[i]->title() != "\b")) {
848 			v_count.erase(v_count.begin() + i);
849 			v_prec.erase(v_prec.begin() + i);
850 			vars.erase(vars.begin() + i);
851 		} else {
852 			i++;
853 		}
854 	}
855 	if(mstruct.isComparison()) {
856 		if(feo.test_comparisons || feo.isolate_x) {
857 			mstruct[0].subtract(mstruct[1]);
858 			solve_intervals2(mstruct[0], vars, eo);
859 			mstruct[1].clear(true);
860 		} else {
861 			solve_intervals2(mstruct[0], vars, eo);
862 			solve_intervals2(mstruct[1], vars, eo);
863 		}
864 		return;
865 	}
866 	solve_intervals2(mstruct, vars, eo);
867 }
868 // end functions for handling of interval variables using interval arithmetic
869 
870 
871 /*
872 
873 	Functions for uncertainty calculation using variance formula
874 
875 */
876 
find_interval_create_var(const Number & nr,MathStructure & m,MathStructure & unc,MathStructure & unc2,KnownVariable ** v,KnownVariable ** v2)877 void find_interval_create_var(const Number &nr, MathStructure &m, MathStructure &unc, MathStructure &unc2, KnownVariable **v, KnownVariable **v2) {
878 	if(nr.hasImaginaryPart() && nr.internalImaginary()->isInterval()) {
879 		if(nr.hasRealPart() && nr.isInterval(false)) {
880 			unc = nr.internalImaginary()->uncertainty();
881 			unc2 = nr.realPart().uncertainty();
882 			Number nmid(*nr.internalImaginary());
883 			nmid.intervalToMidValue();
884 			Number nmid2(nr.realPart());
885 			nmid2.intervalToMidValue();
886 			*v = new KnownVariable("", string("(") + format_and_print(nmid) + ")", nmid);
887 			(*v)->setApproximate(false);
888 			*v2 = new KnownVariable("", string("(") + format_and_print(nmid2) + ")", nmid2);
889 			(*v2)->setApproximate(false);
890 			m.set(*v);
891 			m.multiply(nr_one_i);
892 			m.add(*v2);
893 			(*v)->destroy();
894 			(*v2)->destroy();
895 		} else {
896 			unc = nr.internalImaginary()->uncertainty();
897 			Number nmid(*nr.internalImaginary());
898 			nmid.intervalToMidValue();
899 			*v = new KnownVariable("", string("(") + format_and_print(nmid) + ")", nmid);
900 			(*v)->setApproximate(false);
901 			m.set(*v);
902 			m.multiply(nr_one_i);
903 			(*v)->destroy();
904 		}
905 	} else {
906 		unc = nr.uncertainty();
907 		Number nmid(nr);
908 		nmid.intervalToMidValue();
909 		*v = new KnownVariable("", string("(") + format_and_print(nmid) + ")", nmid);
910 		(*v)->setApproximate(false);
911 		m.set(*v);
912 		(*v)->destroy();
913 	}
914 }
915 
find_interval_replace_var(MathStructure & m,MathStructure & unc,MathStructure & unc2,KnownVariable ** v2,const EvaluationOptions & eo,MathStructure * mnew,Variable ** prev_v,bool & b_failed)916 KnownVariable *find_interval_replace_var(MathStructure &m, MathStructure &unc, MathStructure &unc2, KnownVariable **v2, const EvaluationOptions &eo, MathStructure *mnew, Variable **prev_v, bool &b_failed) {
917 	if(eo.approximation != APPROXIMATION_EXACT_VARIABLES && eo.calculate_variables && m.isVariable() && m.variable()->isKnown() && (eo.approximation != APPROXIMATION_EXACT || m.variable()->title() == "\b")) {
918 		const MathStructure &mvar = ((KnownVariable*) m.variable())->get();
919 		if(!mvar.containsInterval(true, true, false, 1, true)) return NULL;
920 		if(mvar.isNumber()) {
921 			m.variable()->ref();
922 			*prev_v = m.variable();
923 			KnownVariable *v = NULL;
924 			find_interval_create_var(mvar.number(), m, unc, unc2, &v, v2);
925 			*mnew = m;
926 			return v;
927 		} else if(mvar.isMultiplication() && mvar[0].isNumber()) {
928 			if(mvar[0].number().isInterval(false)) {
929 				bool b = true;
930 				for(size_t i = 1; i < mvar.size(); i++) {
931 					if(mvar[i].containsInterval(true, true, false, 1, true)) {
932 						b = false;
933 						break;
934 					}
935 				}
936 				if(b) {
937 					m.variable()->ref();
938 					*prev_v = m.variable();
939 					KnownVariable *v = NULL;
940 					find_interval_create_var(mvar[0].number(), m, unc, unc2, &v, v2);
941 					for(size_t i = 1; i < mvar.size(); i++) {
942 						m.multiply(mvar[i], true);
943 					}
944 					*mnew = m;
945 					return v;
946 				}
947 			}
948 		} else if(mvar.isFunction() && mvar.function()->id() == FUNCTION_ID_INTERVAL && mvar.size() == 2 && !mvar[0].containsInterval(true, true, false, 1, true) && !mvar[1].containsInterval(true, true, false, 1, true)) {
949 			if(mvar[0].isAddition() && mvar[0].size() == 2 && mvar[1].isAddition() && mvar[1].size() == 2) {
950 				const MathStructure *mmid = NULL, *munc = NULL;
951 				if(mvar[0][0].equals(mvar[1][0])) {
952 					mmid = &mvar[0][0];
953 					if(mvar[0][1].isNegate() && mvar[0][1][0].equals(mvar[1][1])) munc = &mvar[1][1];
954 					if(mvar[1][1].isNegate() && mvar[1][1][0].equals(mvar[0][1])) munc = &mvar[0][1];
955 				} else if(mvar[0][1].equals(mvar[1][1])) {
956 					mmid = &mvar[0][1];
957 					if(mvar[0][0].isNegate() && mvar[0][0][0].equals(mvar[1][0])) munc = &mvar[1][0];
958 					if(mvar[1][0].isNegate() && mvar[1][0][0].equals(mvar[0][0])) munc = &mvar[0][0];
959 				} else if(mvar[0][0].equals(mvar[1][1])) {
960 					mmid = &mvar[0][0];
961 					if(mvar[0][1].isNegate() && mvar[0][1][0].equals(mvar[1][0])) munc = &mvar[1][0];
962 					if(mvar[1][0].isNegate() && mvar[1][0][0].equals(mvar[0][1])) munc = &mvar[0][1];
963 				} else if(mvar[0][1].equals(mvar[1][0])) {
964 					mmid = &mvar[0][0];
965 					if(mvar[0][0].isNegate() && mvar[0][0][0].equals(mvar[1][1])) munc = &mvar[1][1];
966 					if(mvar[1][1].isNegate() && mvar[1][1][0].equals(mvar[0][0])) munc = &mvar[0][0];
967 				}
968 				if(mmid && munc) {
969 					unc = *munc;
970 					MathStructure mmid2(*mmid);
971 					KnownVariable *v = new KnownVariable("", string("(") + format_and_print(*mmid) + ")", mmid2);
972 					m.set(v);
973 					v->destroy();
974 					return v;
975 				}
976 			}
977 			unc = mvar[1];
978 			unc -= mvar[0];
979 			unc *= nr_half;
980 			MathStructure mmid(mvar[0]);
981 			mmid += mvar[1];
982 			mmid *= nr_half;
983 			KnownVariable *v = new KnownVariable("", string("(") + format_and_print(mmid) + ")", mmid);
984 			m.variable()->ref();
985 			*prev_v = m.variable();
986 			m.set(v);
987 			*mnew = m;
988 			v->destroy();
989 			return v;
990 		} else if(mvar.isFunction() && mvar.function()->id() == FUNCTION_ID_UNCERTAINTY && mvar.size() == 3 && mvar[2].isNumber() && !mvar[0].containsInterval(true, true, false, 1, true) && !mvar[1].containsInterval(true, true, false, 1, true)) {
991 			if(mvar[2].number().getBoolean()) {
992 				unc = mvar[1];
993 				unc *= mvar[0];
994 			} else {
995 				unc = mvar[1];
996 			}
997 			KnownVariable *v = new KnownVariable("", string("(") + format_and_print(mvar[0]) + ")", mvar[0]);
998 			m.variable()->ref();
999 			*prev_v = m.variable();
1000 			m.set(v);
1001 			*mnew = m;
1002 			v->destroy();
1003 			return v;
1004 		}
1005 		b_failed = true;
1006 	} else if(m.isNumber() && m.number().isInterval(false) && m.number().precision(true) <= PRECISION + 10) {
1007 		KnownVariable *v = NULL;
1008 		find_interval_create_var(m.number(), m, unc, unc2, &v, v2);
1009 		return v;
1010 	} else if(m.isFunction() && m.function()->id() == FUNCTION_ID_INTERVAL && m.size() == 2 && !m[0].containsInterval(true, true, false, 1, true) && !m[1].containsInterval(true, true, false, 1, true)) {
1011 		if(m[0].isAddition() && m[0].size() == 2 && m[1].isAddition() && m[1].size() == 2) {
1012 			MathStructure *mmid = NULL, *munc = NULL;
1013 			if(m[0][0].equals(m[1][0])) {
1014 				mmid = &m[0][0];
1015 				if(m[0][1].isNegate() && m[0][1][0].equals(m[1][1])) munc = &m[1][1];
1016 				if(m[1][1].isNegate() && m[1][1][0].equals(m[0][1])) munc = &m[0][1];
1017 			} else if(m[0][1].equals(m[1][1])) {
1018 				mmid = &m[0][1];
1019 				if(m[0][0].isNegate() && m[0][0][0].equals(m[1][0])) munc = &m[1][0];
1020 				if(m[1][0].isNegate() && m[1][0][0].equals(m[0][0])) munc = &m[0][0];
1021 			} else if(m[0][0].equals(m[1][1])) {
1022 				mmid = &m[0][0];
1023 				if(m[0][1].isNegate() && m[0][1][0].equals(m[1][0])) munc = &m[1][0];
1024 				if(m[1][0].isNegate() && m[1][0][0].equals(m[0][1])) munc = &m[0][1];
1025 			} else if(m[0][1].equals(m[1][0])) {
1026 				mmid = &m[0][0];
1027 				if(m[0][0].isNegate() && m[0][0][0].equals(m[1][1])) munc = &m[1][1];
1028 				if(m[1][1].isNegate() && m[1][1][0].equals(m[0][0])) munc = &m[0][0];
1029 			}
1030 			if(mmid && munc) {
1031 				unc = *munc;
1032 				KnownVariable *v = new KnownVariable("", string("(") + format_and_print(*mmid) + ")", *mmid);
1033 				m.set(v);
1034 				v->destroy();
1035 				return v;
1036 			}
1037 		}
1038 		unc = m[1];
1039 		unc -= m[0];
1040 		unc *= nr_half;
1041 		MathStructure mmid(m[0]);
1042 		mmid += m[1];
1043 		mmid *= nr_half;
1044 		KnownVariable *v = new KnownVariable("", string("(") + format_and_print(mmid) + ")", mmid);
1045 		m.set(v);
1046 		v->destroy();
1047 		return v;
1048 	} else if(m.isFunction() && m.function()->id() == FUNCTION_ID_UNCERTAINTY && m.size() == 3 && m[2].isNumber() && !m[0].containsInterval(true, true, false, 1, true) && !m[1].containsInterval(true, true, false, 1, true)) {
1049 		if(m[2].number().getBoolean()) {
1050 			unc = m[1];
1051 			unc *= m[0];
1052 		} else {
1053 			unc = m[1];
1054 		}
1055 		KnownVariable *v = new KnownVariable("", string("(") + format_and_print(m[0]) + ")", m[0]);
1056 		m.set(v);
1057 		v->destroy();
1058 		return v;
1059 	}
1060 	for(size_t i = 0; i < m.size(); i++) {
1061 		KnownVariable *v = find_interval_replace_var(m[i], unc, unc2, v2, eo, mnew, prev_v, b_failed);
1062 		if(b_failed) return NULL;
1063 		if(v) return v;
1064 	}
1065 	return NULL;
1066 }
1067 
find_interval_replace_var_nr(MathStructure & m)1068 bool find_interval_replace_var_nr(MathStructure &m) {
1069 	if((m.isNumber() && m.number().isInterval(false) && m.number().precision(true) <= PRECISION + 10) || (m.isFunction() && m.function()->id() == FUNCTION_ID_INTERVAL && m.size() == 2) || (m.isFunction() && m.function()->id() == FUNCTION_ID_UNCERTAINTY && m.size() == 3)) {
1070 		KnownVariable *v = new KnownVariable("", string("(") + format_and_print(m) + ")", m);
1071 		m.set(v);
1072 		v->destroy();
1073 		return true;
1074 	}
1075 	bool b = false;
1076 	for(size_t i = 0; i < m.size(); i++) {
1077 		if(find_interval_replace_var_nr(m[i])) b = true;
1078 	}
1079 	return b;
1080 }
1081 
1082 
replace_variables_with_interval(MathStructure & m,const EvaluationOptions & eo,bool in_nounit=false,bool only_argument_vars=false)1083 bool replace_variables_with_interval(MathStructure &m, const EvaluationOptions &eo, bool in_nounit = false, bool only_argument_vars = false) {
1084 	if(m.isVariable() && m.variable()->isKnown() && (!only_argument_vars || m.variable()->title() == "\b")) {
1085 		const MathStructure &mvar = ((KnownVariable*) m.variable())->get();
1086 		if(!mvar.containsInterval(true, true, false, 1, true)) return false;
1087 		if(mvar.isNumber()) {
1088 			return false;
1089 		} else if(mvar.isMultiplication() && mvar[0].isNumber()) {
1090 			if(mvar[0].number().isInterval(false)) {
1091 				bool b = true;
1092 				for(size_t i = 1; i < mvar.size(); i++) {
1093 					if(mvar[i].containsInterval(true, true, false, 1, true)) {
1094 						b = false;
1095 						break;
1096 					}
1097 				}
1098 				if(b) return false;
1099 			}
1100 		}
1101 		m.set(mvar, true);
1102 		if(in_nounit) m.removeType(STRUCT_UNIT);
1103 		else m.unformat(eo);
1104 		return true;
1105 	}
1106 	bool b = false;
1107 	if(m.isFunction() && m.function()->id() == FUNCTION_ID_STRIP_UNITS && m.size() == 1) {
1108 		b = replace_variables_with_interval(m[0], eo, true, only_argument_vars);
1109 		if(b && m[0].containsType(STRUCT_UNIT, false, true, true) == 0) {
1110 			m.setToChild(1, true);
1111 		}
1112 		return b;
1113 	}
1114 	for(size_t i = 0; i < m.size(); i++) {
1115 		if(replace_variables_with_interval(m[i], eo, in_nounit, only_argument_vars)) b = true;
1116 	}
1117 	return b;
1118 }
1119 
contains_diff_for(const MathStructure & m,const MathStructure & x_var)1120 bool contains_diff_for(const MathStructure &m, const MathStructure &x_var) {
1121 	if(m.isFunction() && m.function() && m.function()->id() == FUNCTION_ID_DIFFERENTIATE && m.size() >= 2 && m[1] == x_var) return true;
1122 	for(size_t i = 0; i < m.size(); i++) {
1123 		if(contains_diff_for(m[i], x_var)) return true;
1124 	}
1125 	return false;
1126 }
1127 
calculate_uncertainty(MathStructure & m,const EvaluationOptions & eo,bool & b_failed)1128 MathStructure calculate_uncertainty(MathStructure &m, const EvaluationOptions &eo, bool &b_failed) {
1129 	vector<KnownVariable*> vars;
1130 	vector<MathStructure> uncs;
1131 	MathStructure unc, unc2;
1132 	if(eo.approximation != APPROXIMATION_EXACT_VARIABLES && eo.calculate_variables) replace_variables_with_interval(m, eo, false, eo.approximation == APPROXIMATION_EXACT);
1133 	while(true) {
1134 		Variable *prev_v = NULL;
1135 		MathStructure mnew;
1136 		KnownVariable *v2 = NULL;
1137 		KnownVariable *v = find_interval_replace_var(m, unc, unc2, &v2, eo, &mnew, &prev_v, b_failed);
1138 		if(!v) break;
1139 		if(!mnew.isZero()) {
1140 			m.replace(prev_v, mnew);
1141 			prev_v->unref();
1142 		}
1143 		vars.push_back(v);
1144 		uncs.push_back(unc);
1145 		if(v2) {
1146 			vars.push_back(v2);
1147 			uncs.push_back(unc2);
1148 		}
1149 	}
1150 	m.unformat(eo);
1151 	if(eo.sync_units && eo.approximation != APPROXIMATION_EXACT) sync_approximate_units(m, eo, &vars, &uncs, true);
1152 	if(b_failed || vars.empty()) return m_zero;
1153 	MathStructure munc;
1154 	UnknownVariable *uv = new UnknownVariable("", "x");
1155 	MathStructure muv(uv);
1156 	MathStructure *munc_i = NULL;
1157 	for(size_t i = 0; i < vars.size(); i++) {
1158 		if(!vars[i]->get().representsNonComplex(true)) {
1159 			b_failed = true; return m_zero;
1160 		}
1161 		MathStructure *mdiff = new MathStructure(m);
1162 		uv->setInterval(vars[i]->get());
1163 		mdiff->replace(vars[i], muv);
1164 		if(!mdiff->differentiate(muv, eo) || contains_diff_for(*mdiff, muv) || CALCULATOR->aborted()) {
1165 			b_failed = true;
1166 			return m_zero;
1167 		}
1168 		mdiff->replace(muv, vars[i]);
1169 		if(!mdiff->representsNonComplex(true)) {
1170 			MathStructure *mdiff_i = new MathStructure(*mdiff);
1171 			mdiff->transformById(FUNCTION_ID_RE);
1172 			mdiff_i->transformById(FUNCTION_ID_IM);
1173 			mdiff_i->raise(nr_two);
1174 			mdiff_i->multiply(uncs[i]);
1175 			mdiff_i->last().raise(nr_two);
1176 			if(!munc_i) {munc_i = mdiff_i;}
1177 			else munc_i->add_nocopy(mdiff_i, true);
1178 		}
1179 		mdiff->raise(nr_two);
1180 		mdiff->multiply(uncs[i]);
1181 		mdiff->last().raise(nr_two);
1182 		if(munc.isZero()) {munc.set_nocopy(*mdiff); mdiff->unref();}
1183 		else munc.add_nocopy(mdiff, true);
1184 	}
1185 	uv->destroy();
1186 	munc.raise(nr_half);
1187 	if(munc_i) {
1188 		munc_i->raise(nr_half);
1189 		munc_i->multiply(nr_one_i);
1190 		munc.add_nocopy(munc_i);
1191 	}
1192 	return munc;
1193 }
1194 
find_interval_replace_var_comp(MathStructure & m,const EvaluationOptions & eo,Variable ** v)1195 Variable *find_interval_replace_var_comp(MathStructure &m, const EvaluationOptions &eo, Variable **v) {
1196 	if(eo.approximation != APPROXIMATION_EXACT && eo.approximation != APPROXIMATION_EXACT_VARIABLES && eo.calculate_variables && m.isVariable() && m.variable()->isKnown() && ((KnownVariable*) m.variable())->get().containsInterval(true, true, false, 1, true)) {
1197 		UnknownVariable *uv = new UnknownVariable("", format_and_print(m));
1198 		uv->setInterval(m);
1199 		*v = m.variable();
1200 		m.set(uv, true);
1201 		return uv;
1202 	} else if((m.isNumber() && m.number().isInterval(false) && m.number().precision(true) <= PRECISION + 10) || (m.isFunction() && m.function()->id() == FUNCTION_ID_INTERVAL && m.size() == 2) || (m.isFunction() && m.function()->id() == FUNCTION_ID_UNCERTAINTY && m.size() == 3)) {
1203 		Variable *uv = NULL;
1204 		if(eo.approximation == APPROXIMATION_EXACT || eo.approximation == APPROXIMATION_EXACT_VARIABLES) {
1205 			uv = new KnownVariable("", string("(") + format_and_print(m) + ")", m);
1206 		} else {
1207 			uv = new UnknownVariable("", string("(") + format_and_print(m) + ")");
1208 			((UnknownVariable*) uv)->setInterval(m);
1209 		}
1210 		*v = NULL;
1211 		m.set(uv, true);
1212 		return uv;
1213 	}
1214 	for(size_t i = 0; i < m.size(); i++) {
1215 		Variable *uv = find_interval_replace_var_comp(m[i], eo, v);
1216 		if(uv) return uv;
1217 	}
1218 	return NULL;
1219 }
1220 
eval_comparison_sides(MathStructure & m,const EvaluationOptions & eo)1221 bool eval_comparison_sides(MathStructure &m, const EvaluationOptions &eo) {
1222 	if(m.isComparison()) {
1223 		MathStructure mbak(m);
1224 		if(!m[0].isUnknown()) {
1225 			bool ret = true;
1226 			CALCULATOR->beginTemporaryStopMessages();
1227 			m[0].eval(eo);
1228 			if(m[0].containsFunctionId(FUNCTION_ID_UNCERTAINTY) && !mbak[0].containsFunctionId(FUNCTION_ID_UNCERTAINTY)) {
1229 				CALCULATOR->endTemporaryStopMessages();
1230 				m[0] = mbak[0];
1231 				ret = false;
1232 			} else {
1233 				CALCULATOR->endTemporaryStopMessages(true);
1234 			}
1235 			CALCULATOR->beginTemporaryStopMessages();
1236 			m[1].eval(eo);
1237 			if(m[1].containsFunctionId(FUNCTION_ID_UNCERTAINTY) && !mbak[1].containsFunctionId(FUNCTION_ID_UNCERTAINTY)) {
1238 				CALCULATOR->endTemporaryStopMessages();
1239 				m[1] = mbak[1];
1240 				ret = false;
1241 			} else {
1242 				CALCULATOR->endTemporaryStopMessages(true);
1243 			}
1244 			if(ret && !m.containsUnknowns()) {
1245 				m.calculatesub(eo, eo, false);
1246 				return true;
1247 			}
1248 			return false;
1249 		} else {
1250 			m[1].eval(eo);
1251 			m.calculatesub(eo, eo, false);
1252 			return true;
1253 		}
1254 	} else if(m.containsType(STRUCT_COMPARISON)) {
1255 		bool ret = true;
1256 		for(size_t i = 0; i < m.size(); i++) {
1257 			if(!eval_comparison_sides(m[i], eo)) ret = false;
1258 		}
1259 		m.childrenUpdated();
1260 		m.calculatesub(eo, eo, false);
1261 		return ret;
1262 	} else {
1263 		m.eval(eo);
1264 	}
1265 	return true;
1266 }
1267 
separate_unit_vars(MathStructure & m,const EvaluationOptions & eo,bool only_approximate,bool dry_run)1268 bool separate_unit_vars(MathStructure &m, const EvaluationOptions &eo, bool only_approximate, bool dry_run) {
1269 	if(m.isVariable() && m.variable()->isKnown()) {
1270 		const MathStructure &mvar = ((KnownVariable*) m.variable())->get();
1271 		if(mvar.isMultiplication()) {
1272 			bool b = false;
1273 			for(size_t i = 0; i < mvar.size(); i++) {
1274 				if(is_unit_multiexp(mvar[i])) {
1275 					if(!b) b = !only_approximate || contains_approximate_relation_to_base(mvar[i], true);
1276 				} else if(mvar[i].containsType(STRUCT_UNIT, false, true, true) != 0) {
1277 					b = false;
1278 					break;
1279 				}
1280 			}
1281 			if(!b) return false;
1282 			if(dry_run) return true;
1283 			m.transformById(FUNCTION_ID_STRIP_UNITS);
1284 			for(size_t i = 0; i < mvar.size(); i++) {
1285 				if(is_unit_multiexp(mvar[i])) {
1286 					m.multiply(mvar[i], i);
1287 				}
1288 			}
1289 			m.unformat(eo);
1290 			return true;
1291 		}
1292 	}
1293 	if(m.isFunction() && m.function()->id() == FUNCTION_ID_STRIP_UNITS) return false;
1294 	bool b = false;
1295 	for(size_t i = 0; i < m.size(); i++) {
1296 		if(separate_unit_vars(m[i], eo, only_approximate, dry_run)) {
1297 			b = true;
1298 			if(dry_run) return true;
1299 		}
1300 	}
1301 	return b;
1302 }
1303 // end functions for uncertainty calculation using variance formula
1304 
1305 // Functions for handling of function arguments with intervals replaced by temporary variables
1306 int contains_interval_var(const MathStructure &m, bool structural_only, bool check_variables, bool check_functions, int ignore_high_precision_interval, bool include_interval_function);
contains_function_interval(const MathStructure & m,bool structural_only=true,bool check_variables=false,bool check_functions=false,int ignore_high_precision_interval=0,bool include_interval_function=false)1307 int contains_function_interval(const MathStructure &m, bool structural_only = true, bool check_variables = false, bool check_functions = false, int ignore_high_precision_interval = 0, bool include_interval_function = false) {
1308 	for(size_t i = 0; i < m.size(); i++) {
1309 		if(contains_function_interval(m[i], structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function)) return true;
1310 	}
1311 	if(m.isVariable() && m.variable()->isKnown() && m.variable()->title() == "\b") {
1312 		if(ignore_high_precision_interval == 0) return true;
1313 		return contains_interval_var(((KnownVariable*) m.variable())->get(), structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function);
1314 	}
1315 	return false;
1316 }
replace_function_vars(MathStructure & m)1317 bool replace_function_vars(MathStructure &m) {
1318 	for(size_t i = 0; i < m.size(); i++) {
1319 		if(replace_function_vars(m[i])) return true;
1320 	}
1321 	if(m.isVariable() && m.variable()->isKnown() && m.variable()->title() == "\b") {
1322 		m.set(((KnownVariable*) m.variable())->get(), true);
1323 	}
1324 	return false;
1325 }
1326 
1327 // Simplify expressions by combining sin() and cos()
simplify_functions(MathStructure & mstruct,const EvaluationOptions & eo,const EvaluationOptions & feo,const MathStructure & x_var)1328 bool simplify_functions(MathStructure &mstruct, const EvaluationOptions &eo, const EvaluationOptions &feo, const MathStructure &x_var) {
1329 	if(!mstruct.isAddition()) {
1330 		bool b = false;
1331 		for(size_t i = 0; i < mstruct.size(); i++) {
1332 			if(CALCULATOR->aborted()) break;
1333 			if(simplify_functions(mstruct[i], eo, feo, x_var)) {b = true; mstruct.childUpdated(i + 1);}
1334 		}
1335 		return b;
1336 	}
1337 	if(mstruct.containsFunctionId(FUNCTION_ID_SIN, false, false, false) > 0 && mstruct.containsFunctionId(FUNCTION_ID_COS, false, false, false)) {
1338 		if(x_var.isUndefined()) {
1339 			// a*(sin(x)+cos(x))=a*sqrt(2)*sin(x+pi/4)
1340 			bool b_ret = false;
1341 			for(size_t i = 0; i < mstruct.size(); i++) {
1342 				if(mstruct[i].isFunction() && mstruct[i].size() == 1 && mstruct[i].function()->id() == FUNCTION_ID_SIN) {
1343 					for(size_t i2 = 0; i2 < mstruct.size(); i2++) {
1344 						if(i != i2 && mstruct[i2].isFunction() && mstruct[i2].size() == 1 && mstruct[i2].function()->id() == FUNCTION_ID_COS && mstruct[i][0] == mstruct[i2][0]) {
1345 							MathStructure madd(CALCULATOR->getVariableById(VARIABLE_ID_PI));
1346 							madd /= Number(4, 1);
1347 							madd *= CALCULATOR->getRadUnit();
1348 							madd.calculatesub(eo, feo, true);
1349 							mstruct[i][0].calculateAdd(madd, eo);
1350 							mstruct[i].childUpdated(1);
1351 							mstruct.childUpdated(i + 1);
1352 							MathStructure mmul(nr_two);
1353 							mmul.calculateRaise(nr_half, eo);
1354 							mstruct[i].calculateMultiply(mmul, eo);
1355 							mstruct.delChild(i2 + 1);
1356 							b_ret = true;
1357 							break;
1358 						}
1359 					}
1360 				} else if(mstruct[i].isMultiplication()) {
1361 					for(size_t i3 = 0; i3 < mstruct[i].size(); i3++) {
1362 						if(mstruct[i][i3].isFunction() && mstruct[i][i3].size() == 1 && mstruct[i][i3].function()->id() == FUNCTION_ID_SIN) {
1363 							mstruct[i][i3].setFunctionId(FUNCTION_ID_COS);
1364 							bool b = false;
1365 							for(size_t i2 = 0; i2 < mstruct.size(); i2++) {
1366 								if(i != i2 && mstruct[i2] == mstruct[i]) {
1367 									MathStructure madd(CALCULATOR->getVariableById(VARIABLE_ID_PI));
1368 									madd /= Number(4, 1);
1369 									madd *= CALCULATOR->getRadUnit();
1370 									madd.calculatesub(eo, feo, true);
1371 									mstruct[i][i3].setFunctionId(FUNCTION_ID_SIN);
1372 									mstruct[i][i3][0].calculateAdd(madd, eo);
1373 									mstruct[i][i3].childUpdated(1);
1374 									mstruct[i].childUpdated(i3 + 1);
1375 									mstruct.childUpdated(i + 1);
1376 									MathStructure mmul(nr_two);
1377 									mmul.calculateRaise(nr_half, eo);
1378 									mstruct[i].calculateMultiply(mmul, eo);
1379 									mstruct.delChild(i2 + 1);
1380 									b = true;
1381 									break;
1382 								}
1383 							}
1384 							if(b) {
1385 								b_ret = true;
1386 								break;
1387 							} else {
1388 								mstruct[i][i3].setFunctionId(FUNCTION_ID_SIN);
1389 							}
1390 						}
1391 					}
1392 				}
1393 			}
1394 			if(mstruct.size() == 1) mstruct.setToChild(1, true);
1395 			return b_ret;
1396 		} else {
1397 			// a*sin(x)+b*cos(x)=a*sqrt((b/a)^2+1)*sin(x+atan(b/a))
1398 			MathStructure *marg = NULL;
1399 			bool b_cos = false;
1400 			for(size_t i = 0; i < mstruct.size(); i++) {
1401 				if(mstruct[i].isFunction() && mstruct[i].size() == 1 && (mstruct[i].function()->id() == FUNCTION_ID_SIN || mstruct[i].function()->id() == FUNCTION_ID_COS) && mstruct[i][0].contains(x_var)) {
1402 					marg = &mstruct[i][0];
1403 					b_cos = mstruct[i].function()->id() == FUNCTION_ID_COS;
1404 				} else if(mstruct[i].isMultiplication()) {
1405 					for(size_t i2 = 0; i2 < mstruct[i].size(); i2++) {
1406 						if(!marg && mstruct[i][i2].isFunction() && mstruct[i][i2].size() == 1 && (mstruct[i][i2].function()->id() == FUNCTION_ID_SIN || mstruct[i][i2].function()->id() == FUNCTION_ID_COS) && mstruct[i][i2][0].contains(x_var)) {
1407 							marg = &mstruct[i][i2][0];
1408 							b_cos = mstruct[i][i2].function()->id() == FUNCTION_ID_COS;
1409 						} else if(mstruct[i][i2].contains(x_var)) {
1410 							marg = NULL;
1411 							break;
1412 						}
1413 					}
1414 				}
1415 				if(marg) {
1416 					bool b = false;
1417 					for(size_t i3 = i + 1; i3 < mstruct.size(); i3++) {
1418 						if(mstruct[i3].isFunction() && mstruct[i3].size() == 1 && mstruct[i3].function()->id() == (b_cos ? FUNCTION_ID_SIN : FUNCTION_ID_COS) && mstruct[i3][0] == *marg) {
1419 							b = true;
1420 						} else if(mstruct[i3].isMultiplication()) {
1421 							bool b2 = false;
1422 							for(size_t i2 = 0; i2 < mstruct[i3].size(); i2++) {
1423 								if(!b2 && mstruct[i3][i2].isFunction() && mstruct[i3][i2].size() == 1 && (mstruct[i3][i2].function()->id() == FUNCTION_ID_SIN || mstruct[i3][i2].function()->id() == FUNCTION_ID_COS) && mstruct[i3][i2][0] == *marg) {
1424 									if((mstruct[i3][i2].function()->id() == FUNCTION_ID_SIN) == b_cos) b = true;
1425 									b2 = true;
1426 								} else if(mstruct[i3][i2].contains(x_var)) {
1427 									marg = NULL;
1428 									break;
1429 								}
1430 							}
1431 							if(!marg) break;
1432 						}
1433 					}
1434 					if(!b) marg = NULL;
1435 				}
1436 				if(marg) {
1437 					marg->ref();
1438 					MathStructure m_a, m_b;
1439 					for(size_t i3 = i; i3 < mstruct.size();) {
1440 						bool b = false;
1441 						if(mstruct[i3].isFunction() && mstruct[i3].size() == 1 && mstruct[i3].function()->id() == FUNCTION_ID_SIN && mstruct[i3][0] == *marg) {
1442 							if(m_a.isZero()) m_a = m_one;
1443 							else m_a.add(m_one, true);
1444 							b = true;
1445 						} else if(mstruct[i3].isFunction() && mstruct[i3].size() == 1 && mstruct[i3].function()->id() == FUNCTION_ID_COS && mstruct[i3][0] == *marg) {
1446 							if(m_b.isZero()) m_a = m_one;
1447 							else m_b.add(m_one, true);
1448 							b = true;
1449 						} else if(mstruct[i3].isMultiplication()) {
1450 							for(size_t i2 = 0; i2 < mstruct[i3].size(); i2++) {
1451 								if(mstruct[i3][i2].isFunction() && mstruct[i3][i2].size() == 1 && mstruct[i3][i2].function()->id() == FUNCTION_ID_SIN && mstruct[i3][i2][0] == *marg) {
1452 									mstruct[i3].delChild(i2 + 1, true);
1453 									if(m_a.isZero()) m_a.set_nocopy(mstruct[i3]);
1454 									else {mstruct[i3].ref(); m_a.add_nocopy(&mstruct[i3], true);}
1455 									b = true;
1456 									break;
1457 								} else if(mstruct[i3][i2].isFunction() && mstruct[i3][i2].size() == 1 && mstruct[i3][i2].function()->id() == FUNCTION_ID_COS && mstruct[i3][i2][0] == *marg) {
1458 									mstruct[i3].delChild(i2 + 1, true);
1459 									if(m_b.isZero()) m_b.set_nocopy(mstruct[i3]);
1460 									else {mstruct[i3].ref(); m_b.add_nocopy(&mstruct[i3], true);}
1461 									b = true;
1462 									break;
1463 								}
1464 							}
1465 						}
1466 						if(b) {
1467 							mstruct.delChild(i3 + 1);
1468 						} else {
1469 							i3++;
1470 						}
1471 					}
1472 					MathStructure *m_sin = new MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_SIN), NULL);
1473 					m_sin->addChild_nocopy(marg);
1474 					m_b.calculateDivide(m_a, eo);
1475 					MathStructure *m_atan = new MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_ATAN), &m_b, NULL);
1476 					if(m_atan->calculateFunctions(feo)) m_atan->calculatesub(eo, feo, true);
1477 					if(eo.parse_options.angle_unit != ANGLE_UNIT_NONE) m_atan->calculateMultiply(CALCULATOR->getRadUnit(), eo);
1478 					(*m_sin)[0].add_nocopy(m_atan);
1479 					(*m_sin)[0].calculateAddLast(eo);
1480 					m_sin->childUpdated(1);
1481 					m_b.calculateRaise(nr_two, eo);
1482 					m_b.calculateAdd(m_one, eo);
1483 					m_b.calculateRaise(nr_half, eo);
1484 					m_sin->calculateMultiply(m_b, eo);
1485 					m_sin->calculateMultiply(m_a, eo);
1486 					if(mstruct.size() == 0) {mstruct.set_nocopy(*m_sin); m_sin->unref();}
1487 					else mstruct.insertChild_nocopy(m_sin, i + 1);
1488 					simplify_functions(mstruct, eo, feo, x_var);
1489 					return true;
1490 				}
1491 			}
1492 		}
1493 	}
1494 	return false;
1495 }
1496 
1497 // Simplify expressions by combining logarithms
simplify_ln(MathStructure & mstruct)1498 bool simplify_ln(MathStructure &mstruct) {
1499 	bool b_ret = false;
1500 	for(size_t i = 0; i < mstruct.size(); i++) {
1501 		if(simplify_ln(mstruct[i])) b_ret = true;
1502 	}
1503 	if(mstruct.isAddition()) {
1504 		size_t i_ln = (size_t) -1, i_ln_m = (size_t) -1;
1505 		for(size_t i = 0; i < mstruct.size(); i++) {
1506 			if(mstruct[i].isFunction() && mstruct[i].function()->id() == FUNCTION_ID_LOG && mstruct[i].size() == 1 && mstruct[i][0].isNumber() && mstruct[i][0].number().isReal()) {
1507 				if(i_ln == (size_t) -1) {
1508 					i_ln = i;
1509 				} else {
1510 					bool b = true;
1511 					if(mstruct[i_ln].isMultiplication()) {
1512 						if(mstruct[i_ln][1][0].number().raise(mstruct[i_ln][0].number(), true)) {mstruct[i_ln].setToChild(2, true); b_ret = true;}
1513 						else b = false;
1514 					}
1515 					if(b && mstruct[i_ln][0].number().multiply(mstruct[i][0].number())) {
1516 						mstruct.delChild(i + 1);
1517 						i--;
1518 						b_ret = true;
1519 					}
1520 				}
1521 			} else if(mstruct[i].isMultiplication() && mstruct[i].size() == 2 && mstruct[i][1].isFunction() && mstruct[i][1].function()->id() == FUNCTION_ID_LOG && mstruct[i][1].size() == 1 && mstruct[i][1][0].isNumber() && mstruct[i][1][0].number().isReal() && mstruct[i][0].isInteger() && mstruct[i][0].number().isLessThan(1000) && mstruct[i][0].number().isGreaterThan(-1000)) {
1522 				if(mstruct[i][0].number().isPositive()) {
1523 					if(i_ln == (size_t) -1) {
1524 						i_ln = i;
1525 					} else {
1526 						bool b = true;
1527 						if(mstruct[i_ln].isMultiplication()) {
1528 							if(mstruct[i_ln][1][0].number().raise(mstruct[i_ln][0].number())) {mstruct[i_ln].setToChild(2, true); b_ret = true;}
1529 							else b = false;
1530 						}
1531 						if(b && mstruct[i][1][0].number().raise(mstruct[i][0].number(), true)) {
1532 							if(mstruct[i_ln][0].number().multiply(mstruct[i][1][0].number())) {
1533 								mstruct.delChild(i + 1);
1534 								i--;
1535 							} else {
1536 								mstruct[i].setToChild(1, true);
1537 							}
1538 							b_ret = true;
1539 						}
1540 					}
1541 				} else if(mstruct[i][0].number().isNegative()) {
1542 					if(i_ln_m == (size_t) -1) {
1543 						i_ln_m = i;
1544 					} else {
1545 						bool b = mstruct[i_ln_m][0].number().isMinusOne();
1546 						if(!b && mstruct[i_ln_m][1][0].number().raise(-mstruct[i_ln_m][0].number())) {mstruct[i_ln_m][0].set(m_minus_one, true); b_ret = true; b = true;}
1547 						bool b_m1 = b && mstruct[i][0].number().isMinusOne();
1548 						if(b && (b_m1 || mstruct[i][1][0].number().raise(-mstruct[i][0].number(), true))) {
1549 							if(mstruct[i_ln_m][1][0].number().multiply(mstruct[i][1][0].number())) {
1550 								mstruct.delChild(i + 1);
1551 								b_ret = true;
1552 								i--;
1553 							} else if(!b_m1) b_ret = true;
1554 						}
1555 					}
1556 				}
1557 			}
1558 		}
1559 		if(mstruct.size() == 1) mstruct.setToChild(1, true);
1560 	}
1561 	return b_ret;
1562 }
1563 
simplify_roots(MathStructure & mstruct,const EvaluationOptions & eo)1564 bool simplify_roots(MathStructure &mstruct, const EvaluationOptions &eo) {
1565 	bool b_ret = false;
1566 	for(size_t i = 0; i < mstruct.size(); i++) {
1567 		if(simplify_roots(mstruct[i], eo)) {
1568 			mstruct.childUpdated(i + 1);
1569 			b_ret = true;
1570 		}
1571 	}
1572 	if(mstruct.isMultiplication() && mstruct.size() >= 2 && mstruct[0].isNumber() && mstruct[0].number().isRational()) {
1573 		for(size_t i = 1; i < mstruct.size(); i++) {
1574 			if(mstruct[i].isPower() && mstruct[i][1].isNumber() && !mstruct[i][1].number().includesInfinity() && mstruct[i][0].isNumber() && mstruct[i][0].number().isRational() && !mstruct[i][0].number().isZero()) {
1575 				if(mstruct[0].number().denominator() == mstruct[i][0].number().numerator() && mstruct[0].number().numerator() == mstruct[i][0].number().denominator()) {
1576 					// (n/m)^a*m/n=(n/m)^(a-1)
1577 					mstruct[i][1].number()--;
1578 					mstruct.childUpdated(i + 1);
1579 					mstruct.delChild(1, true);
1580 					b_ret = true;
1581 					break;
1582 				} else if(mstruct[i][1].number().isNegative() && mstruct[0].number().isIntegerDivisible(mstruct[i][0].number())) {
1583 					if(mstruct[0].number().divide(mstruct[i][0].number())) {
1584 						mstruct[0].numberUpdated();
1585 						mstruct.childUpdated(1);
1586 						mstruct[i][1].number()++;
1587 						b_ret = true;
1588 						if(mstruct[0].isOne()) {mstruct.delChild(1); break;}
1589 					}
1590 				} else if(mstruct[i][1].number().isPositive() && !mstruct[0].number().isInteger() && mstruct[0].number().denominator().isIntegerDivisible(mstruct[i][0].number())) {
1591 					if(mstruct[0].number().multiply(mstruct[i][0].number())) {
1592 						mstruct[0].numberUpdated();
1593 						mstruct.childUpdated(1);
1594 						mstruct[i][1].number()--;
1595 						b_ret = true;
1596 						if(mstruct[0].isOne()) {mstruct.delChild(1, true); break;}
1597 					}
1598 				}
1599 			}
1600 		}
1601 	}
1602 	if(mstruct.isMultiplication()) {
1603 		for(size_t i = 0; i < mstruct.size(); i++) {
1604 			if(mstruct[i].isPower()) {
1605 				for(size_t i2 = i + 1; i2 < mstruct.size();) {
1606 					if(mstruct[i2].isPower() && mstruct[i][0] == mstruct[i2][0]) {
1607 						if(!eo.allow_complex && !mstruct[i][0].representsNonNegative(true) && (!mstruct[i][1].representsInteger() || !mstruct[i2][1].representsInteger())) {
1608 							break;
1609 						}
1610 						mstruct[i][1].add(mstruct[i2][1], true);
1611 						mstruct[i][1].calculateAddLast(eo);
1612 						mstruct.delChild(i2 + 1);
1613 						if(mstruct.size() == 1) {
1614 							mstruct.setToChild(1, true);
1615 							return true;
1616 						}
1617 						b_ret = true;
1618 					} else {
1619 						i2++;
1620 					}
1621 				}
1622 			}
1623 		}
1624 	}
1625 	return b_ret;
1626 }
1627 
1628 // Convert complex numbers from rectangular form
complexToExponentialForm(const EvaluationOptions & eo)1629 bool MathStructure::complexToExponentialForm(const EvaluationOptions &eo) {
1630 	if(m_type == STRUCT_NUMBER && o_number.hasImaginaryPart()) {
1631 		EvaluationOptions eo2 = eo;
1632 		eo2.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR;
1633 		eo2.parse_options.angle_unit = ANGLE_UNIT_RADIANS;
1634 		MathStructure mabs(CALCULATOR->getFunctionById(FUNCTION_ID_ABS), this, NULL);
1635 		MathStructure marg(CALCULATOR->getFunctionById(FUNCTION_ID_ARG), this, NULL);
1636 		marg *= nr_one_i;
1637 		marg.eval(eo2);
1638 		set(CALCULATOR->getVariableById(VARIABLE_ID_E), true);
1639 		raise(marg);
1640 		mabs.eval(eo2);
1641 		if(!mabs.isOne()) multiply(mabs);
1642 		evalSort(false);
1643 		return true;
1644 	}
1645 	if(m_type == STRUCT_POWER) return false;
1646 	bool b = false;
1647 	for(size_t i = 0; i < SIZE; i++) {
1648 		if(CHILD(i).complexToExponentialForm(eo)) {b = true; CHILD_UPDATED(i);}
1649 	}
1650 	return b;
1651 }
complexToPolarForm(const EvaluationOptions & eo)1652 bool MathStructure::complexToPolarForm(const EvaluationOptions &eo) {
1653 	if(m_type == STRUCT_NUMBER && o_number.hasImaginaryPart()) {
1654 		MathStructure mabs(CALCULATOR->getFunctionById(FUNCTION_ID_ABS), this, NULL);
1655 		MathStructure marg(CALCULATOR->getFunctionById(FUNCTION_ID_ARG), this, NULL);
1656 		EvaluationOptions eo2 = eo;
1657 		eo2.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR;
1658 		mabs.eval(eo2);
1659 		marg.eval(eo2);
1660 		switch(eo2.parse_options.angle_unit) {
1661 			case ANGLE_UNIT_DEGREES: {if(CALCULATOR->getDegUnit()) {marg.multiply(CALCULATOR->getDegUnit(), true);} break;}
1662 			case ANGLE_UNIT_GRADIANS: {if(CALCULATOR->getGraUnit()) {marg.multiply(CALCULATOR->getGraUnit(), true);} break;}
1663 			case ANGLE_UNIT_RADIANS: {if(CALCULATOR->getRadUnit()) {marg.multiply(CALCULATOR->getRadUnit(), true);} break;}
1664 			default: {break;}
1665 		}
1666 		set(marg, true);
1667 		transformById(FUNCTION_ID_SIN);
1668 		multiply(nr_one_i);
1669 		add_nocopy(new MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_COS), &marg, NULL));
1670 		if(!mabs.isOne()) multiply(mabs);
1671 		evalSort(true);
1672 		return true;
1673 	} else if(m_type == STRUCT_POWER && CHILD(0).isVariable() && CHILD(0).variable()->id() == VARIABLE_ID_E && CHILD(1).isNumber() && CHILD(1).number().hasImaginaryPart() && !CHILD(1).number().hasRealPart()) {
1674 		MathStructure marg(CHILD(1).number().imaginaryPart());
1675 		EvaluationOptions eo2 = eo;
1676 		eo2.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR;
1677 		switch(eo2.parse_options.angle_unit) {
1678 			case ANGLE_UNIT_DEGREES: {if(CALCULATOR->getDegUnit()) {marg.calculateMultiply(Number(180, 1), eo2); marg.calculateDivide(CALCULATOR->getVariableById(VARIABLE_ID_PI), eo2); marg.multiply(CALCULATOR->getDegUnit(), true);} break;}
1679 			case ANGLE_UNIT_GRADIANS: {if(CALCULATOR->getGraUnit()) {marg.calculateMultiply(Number(200, 1), eo2); marg.calculateDivide(CALCULATOR->getVariableById(VARIABLE_ID_PI), eo2); marg.multiply(CALCULATOR->getGraUnit(), true);} break;}
1680 			case ANGLE_UNIT_RADIANS: {if(CALCULATOR->getRadUnit()) {marg.multiply(CALCULATOR->getRadUnit(), true);} break;}
1681 			default: {break;}
1682 		}
1683 		set(marg, true);
1684 		transformById(FUNCTION_ID_SIN);
1685 		multiply(nr_one_i);
1686 		add_nocopy(new MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_COS), &marg, NULL));
1687 		evalSort(true);
1688 		return true;
1689 	} else if(m_type == STRUCT_MULTIPLICATION && SIZE == 2 && CHILD(1).isPower() && CHILD(1)[0].isVariable() && CHILD(1)[0].variable()->id() == VARIABLE_ID_E && CHILD(1)[1].isNumber() && CHILD(1)[1].number().hasImaginaryPart() && !CHILD(1)[1].number().hasRealPart() && CHILD(0).isNumber() && !CHILD(0).number().hasImaginaryPart()) {
1690 		MathStructure marg(CHILD(1)[1].number().imaginaryPart());
1691 		EvaluationOptions eo2 = eo;
1692 		eo2.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR;
1693 		switch(eo2.parse_options.angle_unit) {
1694 			case ANGLE_UNIT_DEGREES: {if(CALCULATOR->getDegUnit()) {marg.calculateMultiply(Number(180, 1), eo2); marg.calculateDivide(CALCULATOR->getVariableById(VARIABLE_ID_PI), eo2); marg.multiply(CALCULATOR->getDegUnit(), true);} break;}
1695 			case ANGLE_UNIT_GRADIANS: {if(CALCULATOR->getGraUnit()) {marg.calculateMultiply(Number(200, 1), eo2); marg.calculateDivide(CALCULATOR->getVariableById(VARIABLE_ID_PI), eo2); marg.multiply(CALCULATOR->getGraUnit(), true);} break;}
1696 			case ANGLE_UNIT_RADIANS: {if(CALCULATOR->getRadUnit()) {marg.multiply(CALCULATOR->getRadUnit(), true);} break;}
1697 			default: {break;}
1698 		}
1699 		CHILD(1).set(marg, true);
1700 		CHILD(1).transformById(FUNCTION_ID_SIN);
1701 		CHILD(1).multiply(nr_one_i);
1702 		CHILD(1).add_nocopy(new MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_COS), &marg, NULL));
1703 		CHILD_UPDATED(1)
1704 		evalSort(true);
1705 		return true;
1706 	}
1707 	if(m_type == STRUCT_POWER || m_type == STRUCT_FUNCTION) return false;
1708 	bool b = false;
1709 	for(size_t i = 0; i < SIZE; i++) {
1710 		if(CHILD(i).complexToPolarForm(eo)) {b = true; CHILD_UPDATED(i);}
1711 	}
1712 	return b;
1713 }
complexToCisForm(const EvaluationOptions & eo)1714 bool MathStructure::complexToCisForm(const EvaluationOptions &eo) {
1715 	if(m_type == STRUCT_NUMBER && o_number.hasImaginaryPart()) {
1716 		MathStructure mabs(CALCULATOR->getFunctionById(FUNCTION_ID_ABS), this, NULL);
1717 		MathStructure marg(CALCULATOR->getFunctionById(FUNCTION_ID_ARG), this, NULL);
1718 		EvaluationOptions eo2 = eo;
1719 		eo2.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR;
1720 		mabs.eval(eo2);
1721 		marg.eval(eo2);
1722 		switch(eo2.parse_options.angle_unit) {
1723 			case ANGLE_UNIT_DEGREES: {if(CALCULATOR->getDegUnit()) {marg.multiply(CALCULATOR->getDegUnit(), true);} break;}
1724 			case ANGLE_UNIT_GRADIANS: {if(CALCULATOR->getGraUnit()) {marg.multiply(CALCULATOR->getGraUnit(), true);} break;}
1725 			default: {break;}
1726 		}
1727 		set(marg, true);
1728 		transformById(FUNCTION_ID_CIS);
1729 		multiply(mabs);
1730 		evalSort(true);
1731 		return true;
1732 	} else if(m_type == STRUCT_POWER && CHILD(0).isVariable() && CHILD(0).variable()->id() == VARIABLE_ID_E && CHILD(1).isNumber() && CHILD(1).number().hasImaginaryPart() && !CHILD(1).number().hasRealPart()) {
1733 		set(CHILD(1).number().imaginaryPart(), true);
1734 		EvaluationOptions eo2 = eo;
1735 		eo2.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR;
1736 		switch(eo2.parse_options.angle_unit) {
1737 			case ANGLE_UNIT_DEGREES: {if(CALCULATOR->getDegUnit()) {calculateMultiply(Number(180, 1), eo2); calculateDivide(CALCULATOR->getVariableById(VARIABLE_ID_PI), eo2); multiply(CALCULATOR->getDegUnit(), true);} break;}
1738 			case ANGLE_UNIT_GRADIANS: {if(CALCULATOR->getGraUnit()) {calculateMultiply(Number(200, 1), eo2); calculateDivide(CALCULATOR->getVariableById(VARIABLE_ID_PI), eo2); multiply(CALCULATOR->getGraUnit(), true);} break;}
1739 			default: {break;}
1740 		}
1741 		transformById(FUNCTION_ID_CIS);
1742 		multiply(m_one);
1743 		evalSort(true);
1744 		return true;
1745 	} else if(m_type == STRUCT_MULTIPLICATION && SIZE == 2 && CHILD(1).isPower() && CHILD(1)[0].isVariable() && CHILD(1)[0].variable()->id() == VARIABLE_ID_E && CHILD(1)[1].isNumber() && CHILD(1)[1].number().hasImaginaryPart() && !CHILD(1)[1].number().hasRealPart() && CHILD(0).isNumber() && !CHILD(0).number().hasImaginaryPart()) {
1746 		CHILD(1).set(CHILD(1)[1].number().imaginaryPart(), true);
1747 		EvaluationOptions eo2 = eo;
1748 		eo2.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR;
1749 		switch(eo2.parse_options.angle_unit) {
1750 			case ANGLE_UNIT_DEGREES: {if(CALCULATOR->getDegUnit()) {CHILD(1).calculateMultiply(Number(180, 1), eo2); CHILD(1).calculateDivide(CALCULATOR->getVariableById(VARIABLE_ID_PI), eo2); CHILD(1).multiply(CALCULATOR->getDegUnit(), true);} break;}
1751 			case ANGLE_UNIT_GRADIANS: {if(CALCULATOR->getGraUnit()) {CHILD(1).calculateMultiply(Number(200, 1), eo2); CHILD(1).calculateDivide(CALCULATOR->getVariableById(VARIABLE_ID_PI), eo2); CHILD(1).multiply(CALCULATOR->getGraUnit(), true);} break;}
1752 			default: {break;}
1753 		}
1754 		CHILD(1).transformById(FUNCTION_ID_CIS);
1755 		CHILD_UPDATED(1)
1756 		return true;
1757 	}
1758 	bool b = false;
1759 	for(size_t i = 0; i < SIZE; i++) {
1760 		if(CHILD(i).complexToCisForm(eo)) {b = true; CHILD_UPDATED(i);}
1761 	}
1762 	return b;
1763 }
1764 
convert_to_default_angle_unit(MathStructure & m,const EvaluationOptions & eo)1765 bool convert_to_default_angle_unit(MathStructure &m, const EvaluationOptions &eo) {
1766 	bool b = false;
1767 	for(size_t i = 0; i < m.size(); i++) {
1768 		if(convert_to_default_angle_unit(m[i], eo)) b = true;
1769 		if(m.isFunction() && m.function()->getArgumentDefinition(i + 1) && m.function()->getArgumentDefinition(i + 1)->type() == ARGUMENT_TYPE_ANGLE) {
1770 			Unit *u = NULL;
1771 			if(eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES) u = CALCULATOR->getDegUnit();
1772 			else if(eo.parse_options.angle_unit == ANGLE_UNIT_GRADIANS) u = CALCULATOR->getGraUnit();
1773 			if(u && m[i].contains(CALCULATOR->getRadUnit(), false, false, false)) {
1774 				m[i].divide(u);
1775 				m[i].multiply(u);
1776 				EvaluationOptions eo2 = eo;
1777 				if(eo.approximation == APPROXIMATION_TRY_EXACT) eo2.approximation = APPROXIMATION_APPROXIMATE;
1778 				eo2.calculate_functions = false;
1779 				eo2.sync_units = true;
1780 				m[i].calculatesub(eo2, eo2, true);
1781 				b = true;
1782 			}
1783 		}
1784 	}
1785 	return b;
1786 }
1787 
1788 // Remove zero unit values if remaining value is not zero (e.g. 5 s + 0 m = 5 s)
remove_add_zero_unit(MathStructure & m)1789 bool remove_add_zero_unit(MathStructure &m) {
1790 	if(m.isAddition() && m.size() > 1) {
1791 		bool b = false, b2 = false;
1792 		for(size_t i = 0; i < m.size(); i++) {
1793 			if(m[i].isMultiplication() && m[i].size() > 1 && m[i][0].isZero() && !m[i].isApproximate()) {
1794 				b = true;
1795 			} else {
1796 				b2 = true;
1797 			}
1798 			if(b && b2) break;
1799 		}
1800 		if(!b || !b2) return false;
1801 		b = false;
1802 		for(size_t i = 0; i < m.size();) {
1803 			b2 = false;
1804 			if(m[i].isMultiplication() && m[i].size() > 1 && m[i][0].isZero() && !m[i].isApproximate()) {
1805 				b2 = true;
1806 				for(size_t i2 = 1; i2 < m[i].size(); i2++) {
1807 					if(!m[i][i2].isUnit_exp() || (m[i][i2].isPower() && m[i][i2][0].unit()->hasNonlinearRelationToBase()) || (m[i][i2].isUnit() && m[i][i2].unit()->hasNonlinearRelationToBase())) {
1808 						b2 = false;
1809 						break;
1810 					}
1811 				}
1812 				if(b2) {
1813 					b = true;
1814 					m.delChild(i + 1);
1815 					if(m.size() == 1) {
1816 						m.setToChild(1, true);
1817 						break;
1818 					}
1819 				}
1820 			}
1821 			if(!b2) i++;
1822 		}
1823 		return b;
1824 	}
1825 	return false;
1826 }
1827 
1828 // Functions for handling log-bases units
find_log_unit(const MathStructure & m,bool toplevel=true)1829 Unit *find_log_unit(const MathStructure &m, bool toplevel = true) {
1830 	if(!toplevel && m.isUnit() && m.unit()->subtype() == SUBTYPE_ALIAS_UNIT && ((AliasUnit*) m.unit())->hasNonlinearExpression() && (((AliasUnit*) m.unit())->expression().find("log") != string::npos || ((AliasUnit*) m.unit())->inverseExpression().find("log") != string::npos || ((AliasUnit*) m.unit())->expression().find("ln") != string::npos || ((AliasUnit*) m.unit())->inverseExpression().find("ln") != string::npos)) {
1831 		return ((AliasUnit*) m.unit())->firstBaseUnit();
1832 	}
1833 	if(m.isMultiplication() && toplevel && m.last().isUnit()) {
1834 		Unit *u = find_log_unit(m.last(), false);
1835 		if(u) {
1836 			for(size_t i = 0; i < m.size(); i++) {
1837 				if(m[i].containsType(STRUCT_UNIT, true)) return u;
1838 			}
1839 			return NULL;
1840 		}
1841 	}
1842 	for(size_t i = 0; i < m.size(); i++) {
1843 		Unit *u = find_log_unit(m[i], false);
1844 		if(u) return u;
1845 	}
1846 	return NULL;
1847 }
convert_log_units(MathStructure & m,const EvaluationOptions & eo)1848 void convert_log_units(MathStructure &m, const EvaluationOptions &eo) {
1849 	while(true) {
1850 		Unit *u = find_log_unit(m);
1851 		if(!u) break;
1852 		if(!m.convert(u, true, NULL, false, eo)) break;
1853 		CALCULATOR->error(false, "Log-based units were converted before calculation.", NULL);
1854 	}
1855 }
1856 
contains_temperature_unit(const MathStructure & m,bool only_cf=true,Unit * u_prev=NULL)1857 Unit *contains_temperature_unit(const MathStructure &m, bool only_cf = true, Unit *u_prev = NULL) {
1858 	if(m.isUnit()) {
1859 		if(!only_cf) {
1860 			if(m.unit() != u_prev && (m.unit() == CALCULATOR->getUnitById(UNIT_ID_KELVIN) || m.unit()->containsRelativeTo(CALCULATOR->getUnitById(UNIT_ID_KELVIN)))) return m.unit();
1861 		} else if(m.unit() == CALCULATOR->getUnitById(UNIT_ID_CELSIUS) || m.unit() == CALCULATOR->getUnitById(UNIT_ID_FAHRENHEIT)) {
1862 			return m.unit();
1863 		}
1864 	}
1865 	if(m.isVariable() && m.variable()->isKnown()) {
1866 		return contains_temperature_unit(((KnownVariable*) m.variable())->get(), only_cf, u_prev);
1867 	}
1868 	if(m.isFunction() && m.function()->id() == FUNCTION_ID_STRIP_UNITS) return NULL;
1869 	for(size_t i = 0; i < m.size(); i++) {
1870 		Unit *u = contains_temperature_unit(m[i], only_cf, u_prev);
1871 		if(u) return u;
1872 	}
1873 	return NULL;
1874 }
separate_temperature_units(MathStructure & m,const EvaluationOptions & eo)1875 bool separate_temperature_units(MathStructure &m, const EvaluationOptions &eo) {
1876 	if(m.isVariable() && m.variable()->isKnown()) {
1877 		const MathStructure &mvar = ((KnownVariable*) m.variable())->get();
1878 		if(contains_temperature_unit(mvar, false)) {
1879 			if(mvar.isMultiplication()) {
1880 				bool b = false;
1881 				for(size_t i = 0; i < mvar.size(); i++) {
1882 					if(is_unit_multiexp(mvar[i])) {
1883 						b = true;
1884 					} else if(mvar[i].containsType(STRUCT_UNIT, false, true, true) != 0) {
1885 						b = false;
1886 						break;
1887 					}
1888 				}
1889 				if(b) {
1890 					m.transformById(FUNCTION_ID_STRIP_UNITS);
1891 					for(size_t i = 0; i < mvar.size(); i++) {
1892 						if(is_unit_multiexp(mvar[i])) {
1893 							m.multiply(mvar[i], i);
1894 						}
1895 					}
1896 					m.unformat(eo);
1897 					separate_temperature_units(m, eo);
1898 					return true;
1899 				}
1900 			}
1901 			if(eo.calculate_variables && ((eo.approximation != APPROXIMATION_EXACT && eo.approximation != APPROXIMATION_EXACT_VARIABLES) || (!m.variable()->isApproximate() && !mvar.containsInterval(true, false, false, 0, true)))) {
1902 				m.set(mvar);
1903 				m.unformat(eo);
1904 				separate_temperature_units(m, eo);
1905 				return true;
1906 			}
1907 		}
1908 	}
1909 	if(m.isFunction() && m.function()->id() == FUNCTION_ID_STRIP_UNITS) return false;
1910 	bool b = false;
1911 	for(size_t i = 0; i < m.size(); i++) {
1912 		if(separate_temperature_units(m[i], eo)) {
1913 			b = true;
1914 		}
1915 	}
1916 	return b;
1917 }
separate_temperature_units2(MathStructure & m,const EvaluationOptions & eo)1918 void separate_temperature_units2(MathStructure &m, const EvaluationOptions &eo) {
1919 	if(m.isMultiplication()) {
1920 		size_t i_unit = m.size();
1921 		for(size_t i = 0; i < m.size(); i++) {
1922 			separate_temperature_units2(m[i], eo);
1923 			if(m[i].isUnit_exp()) {
1924 				if(i_unit < 1 && ((m[i].isUnit() && m[i].unit()->baseUnit() == CALCULATOR->getUnitById(UNIT_ID_KELVIN)) || (m[i].isPower() && m[i][0].unit()->baseUnit() == CALCULATOR->getUnitById(UNIT_ID_KELVIN)))) {
1925 					if(i_unit == i - 1) {
1926 						m[i].multiply(m_one);
1927 						m[i].swapChildren(1, 2);
1928 					} else {
1929 						m[i - 1].ref();
1930 						m[i].multiply_nocopy(&m[i - 1]);
1931 						m.delChild(i);
1932 						i--;
1933 					}
1934 				}
1935 				i_unit = i;
1936 			} else if(i < m.size() && m[i].containsType(STRUCT_UNIT, false, true, true)) {
1937 				MathStructure mtest(m[i]);
1938 				CALCULATOR->beginTemporaryStopMessages();
1939 				mtest.eval(eo);
1940 				if(mtest.containsType(STRUCT_UNIT, false, true, true) > 0) {
1941 					i_unit = i;
1942 				}
1943 				CALCULATOR->endTemporaryStopMessages();
1944 			}
1945 		}
1946 	} else {
1947 		for(size_t i = 0; i < m.size(); i++) {
1948 			separate_temperature_units2(m[i], eo);
1949 		}
1950 	}
1951 }
convert_temperature_units(MathStructure & m,const EvaluationOptions & eo)1952 void convert_temperature_units(MathStructure &m, const EvaluationOptions &eo) {
1953 	if(CALCULATOR->getTemperatureCalculationMode() == TEMPERATURE_CALCULATION_RELATIVE || !CALCULATOR->getUnitById(UNIT_ID_KELVIN)) return;
1954 	Unit *u = contains_temperature_unit(m, true);
1955 	if(!u) return;
1956 	if(!contains_temperature_unit(m, false, u)) {
1957 		if(CALCULATOR->getTemperatureCalculationMode() == TEMPERATURE_CALCULATION_HYBRID) return;
1958 		MathStructure *mp = &m;
1959 		if(m.isMultiplication() && m.size() == 2 && m[0].isMinusOne()) mp = &m[1];
1960 		if(mp->isUnit_exp()) return;
1961 		if(mp->isMultiplication() && mp->size() > 0 && mp->last().isUnit_exp()) {
1962 			bool b = false;
1963 			for(size_t i = 0; i < mp->size() - 1; i++) {
1964 				if(contains_temperature_unit((*mp)[i], true)) {b = true; break;}
1965 			}
1966 			if(!b) return;
1967 		}
1968 	}
1969 	separate_temperature_units(m, eo);
1970 	separate_temperature_units2(m, eo);
1971 	m.convert(CALCULATOR->getUnitById(UNIT_ID_KELVIN), true, NULL, false, eo);
1972 }
1973 
warn_ratio_units(MathStructure & m,bool top_level=true)1974 bool warn_ratio_units(MathStructure &m, bool top_level = true) {
1975 	if(!top_level && m.isUnit() && ((m.unit()->subtype() == SUBTYPE_BASE_UNIT && m.unit()->referenceName() == "Np") || (m.unit()->subtype() == SUBTYPE_ALIAS_UNIT && ((AliasUnit*) m.unit())->baseUnit()->referenceName() == "Np"))) {
1976 		CALCULATOR->error(true, "Logarithmic ratio units is treated as other units and the result might not be as expected.", NULL);
1977 		return true;
1978 	}
1979 	if(m.isMultiplication() && top_level && m.last().isUnit()) {
1980 		if(m.size() < 2) return false;
1981 		for(size_t i = 0; i < m.size() - 1; i++) {
1982 			if(warn_ratio_units(m[i], false)) return true;
1983 		}
1984 	} else {
1985 		for(size_t i = 0; i < m.size(); i++) {
1986 			if(warn_ratio_units(m[i], false)) return true;
1987 		}
1988 	}
1989 	return false;
1990 }
1991 
clean_multiplications(MathStructure & mstruct)1992 void clean_multiplications(MathStructure &mstruct) {
1993 	if(mstruct.isMultiplication()) {
1994 		for(size_t i = 0; i < mstruct.size(); i++) {
1995 			if(mstruct[i].isMultiplication()) {
1996 				size_t i2 = 0;
1997 				for(; i2 < mstruct[i + i2].size(); i2++) {
1998 					mstruct[i + i2][i2].ref();
1999 					mstruct.insertChild_nocopy(&mstruct[i + i2][i2], i + i2 + 1);
2000 				}
2001 				mstruct.delChild(i + i2 + 1);
2002 			}
2003 		}
2004 	}
2005 	for(size_t i = 0; i < mstruct.size(); i++) {
2006 		clean_multiplications(mstruct[i]);
2007 	}
2008 }
2009 
2010 // Attempt to isolate x and test validity afterwards
try_isolate_x(MathStructure & mstruct,EvaluationOptions & eo3,const EvaluationOptions & eo)2011 bool try_isolate_x(MathStructure &mstruct, EvaluationOptions &eo3, const EvaluationOptions &eo) {
2012 	if(mstruct.isProtected()) return false;
2013 	if(mstruct.isComparison()) {
2014 		CALCULATOR->beginTemporaryStopMessages();
2015 		MathStructure mtest(mstruct);
2016 		eo3.test_comparisons = false;
2017 		eo3.warn_about_denominators_assumed_nonzero = false;
2018 		mtest[0].calculatesub(eo3, eo);
2019 		mtest[1].calculatesub(eo3, eo);
2020 		eo3.test_comparisons = eo.test_comparisons;
2021 		const MathStructure *x_var2;
2022 		if(eo.isolate_var) x_var2 = eo.isolate_var;
2023 		else x_var2 = &mstruct.find_x_var();
2024 		if(x_var2->isUndefined() || (mtest[0] == *x_var2 && !mtest[1].contains(*x_var2))) {
2025 			CALCULATOR->endTemporaryStopMessages();
2026 			 return false;
2027 		}
2028 		if(mtest.isolate_x(eo3, eo, *x_var2, false)) {
2029 			if(test_comparisons(mstruct, mtest, *x_var2, eo3) >= 0) {
2030 				CALCULATOR->endTemporaryStopMessages(true);
2031 				mstruct = mtest;
2032 				return true;
2033 			}
2034 		}
2035 		CALCULATOR->endTemporaryStopMessages();
2036 	} else {
2037 		bool b = false;
2038 		for(size_t i = 0; i < mstruct.size(); i++) {
2039 			if(try_isolate_x(mstruct[i], eo3, eo)) b = true;
2040 		}
2041 		return b;
2042 	}
2043 	return false;
2044 }
2045 
simplify(const EvaluationOptions & eo,bool unfactorize)2046 bool MathStructure::simplify(const EvaluationOptions &eo, bool unfactorize) {
2047 	if(SIZE == 0) return false;
2048 	if(unfactorize) {
2049 		unformat();
2050 		EvaluationOptions eo2 = eo;
2051 		eo2.expand = true;
2052 		eo2.combine_divisions = false;
2053 		eo2.sync_units = false;
2054 		calculatesub(eo2, eo2);
2055 		bool b = do_simplification(*this, eo2, true, false, false);
2056 		return combination_factorize(*this) || b;
2057 	}
2058 	return combination_factorize(*this);
2059 }
expand(const EvaluationOptions & eo,bool unfactorize)2060 bool MathStructure::expand(const EvaluationOptions &eo, bool unfactorize) {
2061 	if(SIZE == 0) return false;
2062 	EvaluationOptions eo2 = eo;
2063 	eo2.sync_units = false;
2064 	eo2.expand = true;
2065 	if(unfactorize) calculatesub(eo2, eo2);
2066 	do_simplification(*this, eo2, true, false, false);
2067 	return false;
2068 }
structure(StructuringMode structuring,const EvaluationOptions & eo,bool restore_first)2069 bool MathStructure::structure(StructuringMode structuring, const EvaluationOptions &eo, bool restore_first) {
2070 	switch(structuring) {
2071 		case STRUCTURING_NONE: {
2072 			if(restore_first) {
2073 				EvaluationOptions eo2 = eo;
2074 				eo2.sync_units = false;
2075 				calculatesub(eo2, eo2);
2076 			}
2077 			return false;
2078 		}
2079 		case STRUCTURING_FACTORIZE: {
2080 			return factorize(eo, restore_first, 3, 0, true, 2, NULL, m_undefined, true, false, -1);
2081 		}
2082 		default: {
2083 			return simplify(eo, restore_first);
2084 		}
2085 	}
2086 }
2087 
2088 #define FORMAT_COMPLEX_NUMBERS	if(eo.complex_number_form == COMPLEX_NUMBER_FORM_EXPONENTIAL) complexToExponentialForm(eo); \
2089 				else if(eo.complex_number_form == COMPLEX_NUMBER_FORM_POLAR) complexToPolarForm(eo); \
2090 				else if(eo.complex_number_form == COMPLEX_NUMBER_FORM_CIS) complexToCisForm(eo);
2091 
eval(const EvaluationOptions & eo)2092 MathStructure &MathStructure::eval(const EvaluationOptions &eo) {
2093 
2094 	if(m_type == STRUCT_NUMBER) {FORMAT_COMPLEX_NUMBERS; return *this;}
2095 
2096 	if(eo.structuring != STRUCTURING_NONE) warn_ratio_units(*this);
2097 
2098 	unformat(eo);
2099 
2100 	if(m_type == STRUCT_UNDEFINED || m_type == STRUCT_ABORTED || m_type == STRUCT_DATETIME || m_type == STRUCT_UNIT || m_type == STRUCT_SYMBOLIC || (m_type == STRUCT_VARIABLE && !o_variable->isKnown())) return *this;
2101 
2102 	if(eo.structuring != STRUCTURING_NONE && eo.sync_units) {
2103 		convert_log_units(*this, eo);
2104 		convert_temperature_units(*this, eo);
2105 	}
2106 
2107 	EvaluationOptions feo = eo;
2108 	feo.structuring = STRUCTURING_NONE;
2109 	feo.do_polynomial_division = false;
2110 	feo.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR;
2111 	EvaluationOptions eo2 = eo;
2112 	eo2.structuring = STRUCTURING_NONE;
2113 	eo2.expand = false;
2114 	eo2.test_comparisons = false;
2115 	eo2.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR;
2116 	eo2.isolate_x = false;
2117 
2118 	if(m_type == STRUCT_NUMBER) {FORMAT_COMPLEX_NUMBERS; return *this;}
2119 
2120 	if(eo.interval_calculation == INTERVAL_CALCULATION_INTERVAL_ARITHMETIC) {
2121 		if(eo.calculate_functions) calculate_nondifferentiable_functions(*this, feo, true, true, 0);
2122 		if(((eo.approximation != APPROXIMATION_EXACT && eo.approximation != APPROXIMATION_EXACT_VARIABLES && eo.calculate_variables) && containsInterval(true, true, false, 1, true)) || (eo.sync_units && eo.approximation != APPROXIMATION_EXACT_VARIABLES && eo.approximation != APPROXIMATION_EXACT && sync_approximate_units(*this, eo)) || (eo.approximation == APPROXIMATION_EXACT && contains_function_interval(*this, true, true, false, 1, true))) {
2123 			EvaluationOptions eo3 = eo2;
2124 			eo3.split_squares = false;
2125 			eo3.assume_denominators_nonzero = false;
2126 			if(eo.approximation == APPROXIMATION_APPROXIMATE && !containsUnknowns()) eo3.approximation = APPROXIMATION_EXACT_VARIABLES;
2127 			else eo3.approximation = APPROXIMATION_EXACT;
2128 			vector<KnownVariable*> vars;
2129 			vector<MathStructure> uncs;
2130 			calculatesub(eo3, eo3);
2131 			while(eo.sync_units && (separate_unit_vars(*this, feo, true) || sync_approximate_units(*this, feo, &vars, &uncs, false))) {
2132 				calculatesub(eo3, eo3);
2133 			}
2134 			eo3.approximation = APPROXIMATION_APPROXIMATE;
2135 			if(eo.sync_units) {
2136 				sync_approximate_units(*this, feo, &vars, &uncs, true);
2137 			}
2138 			factorize_variables(*this, eo3);
2139 			if(eo.approximation == APPROXIMATION_APPROXIMATE && !containsUnknowns()) eo3.approximation = APPROXIMATION_EXACT_VARIABLES;
2140 			else eo3.approximation = APPROXIMATION_EXACT;
2141 			eo3.expand = eo.expand;
2142 			eo3.assume_denominators_nonzero = eo.assume_denominators_nonzero;
2143 			solve_intervals(*this, eo3, feo);
2144 		}
2145 		if(eo.calculate_functions) calculate_differentiable_functions(*this, feo);
2146 	} else if(eo.interval_calculation == INTERVAL_CALCULATION_VARIANCE_FORMULA) {
2147 		if(eo.calculate_functions) calculate_nondifferentiable_functions(*this, feo, true, true, -1);
2148 		if(!isNumber() && (((eo.approximation != APPROXIMATION_EXACT && eo.approximation != APPROXIMATION_EXACT_VARIABLES && eo.calculate_variables) && containsInterval(true, true, false, 1, true)) || containsInterval(true, false, false, 1, true) || (eo.sync_units && eo.approximation != APPROXIMATION_EXACT && sync_approximate_units(*this, eo)) || (eo.approximation == APPROXIMATION_EXACT && contains_function_interval(*this, true, true, false, 1, true)))) {
2149 
2150 			// calculate non-differentiable functions (not handled by variance formula) and functions without uncertainties
2151 			if(eo.calculate_functions) calculate_nondifferentiable_functions(*this, feo, true, true, (eo.approximation != APPROXIMATION_EXACT && eo.approximation != APPROXIMATION_EXACT_VARIABLES && eo.calculate_variables) ? 2 : 1);
2152 
2153 			MathStructure munc, mbak(*this);
2154 			if(eo.approximation != APPROXIMATION_EXACT && eo.approximation != APPROXIMATION_EXACT_VARIABLES && eo.calculate_variables) {
2155 				// replace intervals with variables and calculate exact
2156 				find_interval_replace_var_nr(*this);
2157 				EvaluationOptions eo3 = eo2;
2158 				eo3.split_squares = false;
2159 				if(eo.expand && eo.expand >= -1) eo3.expand = -1;
2160 				eo3.assume_denominators_nonzero = eo.assume_denominators_nonzero;
2161 				eo3.approximation = APPROXIMATION_EXACT;
2162 				vector<KnownVariable*> vars;
2163 				vector<MathStructure> uncs;
2164 				calculatesub(eo3, eo3);
2165 				// remove units from variables with uncertainties
2166 				while(eo.sync_units && (separate_unit_vars(*this, feo, true) || sync_approximate_units(*this, feo, &vars, &uncs, false))) {
2167 					calculatesub(eo3, eo3);
2168 				}
2169 			}
2170 			bool b_failed = false;
2171 			if(containsType(STRUCT_COMPARISON)) {
2172 
2173 				// Handle comparisons by exact calculation followed by calculation of each side of comparisons separately
2174 
2175 				EvaluationOptions eo3 = eo;
2176 				eo3.approximation = APPROXIMATION_EXACT;
2177 				eo3.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC;
2178 				eo3.structuring = STRUCTURING_NONE;
2179 				eo3.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR;
2180 
2181 				// replace uncertain values with variables
2182 				vector<Variable*> vars;
2183 				while(true) {
2184 					Variable *v = NULL;
2185 					Variable *uv = find_interval_replace_var_comp(*this, eo3, &v);
2186 					if(!uv) break;
2187 					if(v) replace(v, uv);
2188 					vars.push_back(uv);
2189 				}
2190 
2191 				eval(eo3);
2192 
2193 				// restore uncertain values
2194 				for(size_t i = 0; i < vars.size(); i++) {
2195 					if(vars[i]->isKnown()) replace(vars[i], ((KnownVariable*) vars[i])->get());
2196 					else replace(vars[i], ((UnknownVariable*) vars[i])->interval());
2197 					vars[i]->destroy();
2198 				}
2199 
2200 				if(CALCULATOR->aborted()) return *this;
2201 
2202 				// calculate each side of comparisons separately
2203 				if(eval_comparison_sides(*this, feo)) {
2204 					if(eo.structuring != STRUCTURING_NONE) {simplify_ln(*this); simplify_roots(*this, eo);}
2205 					structure(eo.structuring, eo2, false);
2206 					if(eo.structuring != STRUCTURING_NONE) {simplify_ln(*this); simplify_roots(*this, eo);}
2207 					clean_multiplications(*this);
2208 				} else if(!CALCULATOR->aborted()) {
2209 					CALCULATOR->error(false, _("Calculation of uncertainty propagation partially failed (using interval arithmetic instead when necessary)."), NULL);
2210 					EvaluationOptions eo4 = eo;
2211 					eo4.interval_calculation = INTERVAL_CALCULATION_INTERVAL_ARITHMETIC;
2212 					eval(eo4);
2213 				}
2214 				return *this;
2215 
2216 			} else {
2217 
2218 				CALCULATOR->beginTemporaryStopMessages();
2219 
2220 				// calcute uncertainty
2221 				munc = calculate_uncertainty(*this, eo, b_failed);
2222 
2223 				if(!b_failed && !munc.isZero()) {
2224 
2225 					EvaluationOptions eo3 = eo;
2226 					eo3.keep_zero_units = false;
2227 					eo3.structuring = STRUCTURING_NONE;
2228 					eo3.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR;
2229 					eo3.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC;
2230 					if(eo3.approximation == APPROXIMATION_TRY_EXACT) eo3.approximation = APPROXIMATION_APPROXIMATE;
2231 
2232 					// evaluate uncertainty and expression without uncertainty
2233 					munc.eval(eo3);
2234 					eo3.keep_zero_units = eo.keep_zero_units;
2235 					eval(eo3);
2236 
2237 					// Add uncertainty to calculated value
2238 					if(eo.keep_zero_units) remove_add_zero_unit(*this);
2239 					b_failed = true;
2240 					if(munc.isFunction() && munc.function()->id() == FUNCTION_ID_ABS && munc.size() == 1) {
2241 						munc.setToChild(1);
2242 					}
2243 					bool one_prepended = false;
2244 					test_munc:
2245 					if(munc.isNumber()) {
2246 						if(munc.isZero()) {
2247 							CALCULATOR->endTemporaryStopMessages(true);
2248 							return *this;
2249 						} else if(isNumber()) {
2250 							o_number.setUncertainty(munc.number());
2251 							numberUpdated();
2252 							CALCULATOR->endTemporaryStopMessages(true);
2253 							return *this;
2254 						} else if(isAddition()) {
2255 							for(size_t i = 0; i < SIZE; i++) {
2256 								if(CHILD(i).isNumber()) {
2257 									b_failed = false;
2258 									CHILD(i).number().setUncertainty(munc.number());
2259 									CHILD(i).numberUpdated();
2260 									CHILD_UPDATED(i);
2261 									break;
2262 								}
2263 							}
2264 						}
2265 					} else {
2266 						if(munc.isMultiplication()) {
2267 							if(!munc[0].isNumber()) {
2268 								munc.insertChild(m_one, 1);
2269 								one_prepended = true;
2270 							}
2271 						} else {
2272 							munc.transform(STRUCT_MULTIPLICATION);
2273 							munc.insertChild(m_one, 1);
2274 							one_prepended = true;
2275 						}
2276 						if(munc.isMultiplication()) {
2277 							if(munc.size() == 2) {
2278 								if(isMultiplication() && CHILD(0).isNumber() && (munc[1] == CHILD(1) || (munc[1].isFunction() && munc[1].function()->id() == FUNCTION_ID_ABS && munc[1].size() == 1 && CHILD(1) == munc[1][0]))) {
2279 									CHILD(0).number().setUncertainty(munc[0].number());
2280 									CHILD(0).numberUpdated();
2281 									CHILD_UPDATED(0)
2282 									b_failed = false;
2283 								} else if(equals(munc[1]) || (munc[1].isFunction() && munc[1].function()->id() == FUNCTION_ID_ABS && munc[1].size() == 1 && equals(munc[1][0]))) {
2284 									transform(STRUCT_MULTIPLICATION);
2285 									PREPEND(m_one);
2286 									CHILD(0).number().setUncertainty(munc[0].number());
2287 									CHILD(0).numberUpdated();
2288 									CHILD_UPDATED(0)
2289 									b_failed = false;
2290 								}
2291 							} else if(isMultiplication()) {
2292 								size_t i2 = 0;
2293 								if(CHILD(0).isNumber()) i2++;
2294 								if(SIZE + 1 - i2 == munc.size()) {
2295 									bool b = true;
2296 									for(size_t i = 1; i < munc.size(); i++, i2++) {
2297 										if(!munc[i].equals(CHILD(i2)) && !(munc[i].isFunction() && munc[i].function()->id() == FUNCTION_ID_ABS && munc[i].size() == 1 && CHILD(i2) == munc[i][0])) {
2298 											b = false;
2299 											break;
2300 										}
2301 									}
2302 									if(b) {
2303 										if(!CHILD(0).isNumber()) {
2304 											PREPEND(m_one);
2305 										}
2306 										CHILD(0).number().setUncertainty(munc[0].number());
2307 										CHILD(0).numberUpdated();
2308 										CHILD_UPDATED(0)
2309 										b_failed = false;
2310 									}
2311 								}
2312 							}
2313 							if(b_failed) {
2314 								bool b = false;
2315 								for(size_t i = 0; i < munc.size(); i++) {
2316 									if(munc[i].isFunction() && munc[i].function()->id() == FUNCTION_ID_ABS && munc[i].size() == 1) {
2317 										munc[i].setToChild(1);
2318 										b = true;
2319 									}
2320 								}
2321 								if(b) {
2322 									munc.eval(eo3);
2323 									goto test_munc;
2324 								}
2325 							}
2326 						}
2327 					}
2328 					if(b_failed && munc.countTotalChildren(false) < 50) {
2329 						if(one_prepended && munc.isMultiplication() && munc[0].isOne()) munc.delChild(1, true);
2330 						if(eo.structuring != STRUCTURING_NONE) {simplify_ln(*this); simplify_ln(munc); simplify_roots(*this, eo); simplify_roots(munc, eo);}
2331 						structure(eo.structuring, eo2, false);
2332 						munc.structure(eo.structuring, eo2, false);
2333 						if(eo.structuring != STRUCTURING_NONE) {simplify_ln(*this); simplify_ln(munc); simplify_roots(*this, eo); simplify_roots(munc, eo);}
2334 						clean_multiplications(*this);
2335 						clean_multiplications(munc);
2336 						transformById(FUNCTION_ID_UNCERTAINTY);
2337 						addChild(munc);
2338 						addChild(m_zero);
2339 						CALCULATOR->endTemporaryStopMessages(true);
2340 						return *this;
2341 					}
2342 					if(!b_failed) {
2343 						CALCULATOR->endTemporaryStopMessages(true);
2344 						if(eo.structuring != STRUCTURING_NONE) {simplify_ln(*this); simplify_roots(*this, eo);}
2345 						structure(eo.structuring, eo2, false);
2346 						if(eo.structuring != STRUCTURING_NONE) {simplify_ln(*this); simplify_roots(*this, eo);}
2347 						clean_multiplications(*this);
2348 						return *this;
2349 					}
2350 				}
2351 				CALCULATOR->endTemporaryStopMessages(!b_failed);
2352 				if(b_failed) {
2353 					set(mbak);
2354 					if(CALCULATOR->aborted()) return *this;
2355 					CALCULATOR->error(false, _("Calculation of uncertainty propagation failed (using interval arithmetic instead)."), NULL);
2356 					EvaluationOptions eo3 = eo;
2357 					eo3.interval_calculation = INTERVAL_CALCULATION_INTERVAL_ARITHMETIC;
2358 					eval(eo3);
2359 					return *this;
2360 				}
2361 			}
2362 		}
2363 		if(eo.calculate_functions) calculate_differentiable_functions(*this, feo);
2364 	} else if(eo.calculate_functions) {
2365 		calculateFunctions(feo);
2366 	}
2367 
2368 	if(m_type == STRUCT_NUMBER) {FORMAT_COMPLEX_NUMBERS; return *this;}
2369 
2370 	if(eo2.interval_calculation == INTERVAL_CALCULATION_INTERVAL_ARITHMETIC || eo2.interval_calculation == INTERVAL_CALCULATION_VARIANCE_FORMULA) eo2.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC;
2371 
2372 	// do exact calculations first and handle variables with intervals
2373 	if(eo2.approximation == APPROXIMATION_TRY_EXACT || (eo2.approximation == APPROXIMATION_APPROXIMATE && (containsUnknowns() || containsInterval(false, true, false, 0)))) {
2374 		EvaluationOptions eo3 = eo2;
2375 		if(eo.approximation == APPROXIMATION_APPROXIMATE && !containsUnknowns()) eo3.approximation = APPROXIMATION_EXACT_VARIABLES;
2376 		else eo3.approximation = APPROXIMATION_EXACT;
2377 		eo3.split_squares = false;
2378 		eo3.assume_denominators_nonzero = false;
2379 		calculatesub(eo3, feo);
2380 		if(m_type == STRUCT_NUMBER) {FORMAT_COMPLEX_NUMBERS; return *this;}
2381 		if(eo.interval_calculation < INTERVAL_CALCULATION_INTERVAL_ARITHMETIC && eo.expand && eo.expand >= -1 && !containsType(STRUCT_COMPARISON, true, true, true)) {
2382 			unformat(eo);
2383 			eo3.expand = -1;
2384 			calculatesub(eo3, feo);
2385 		}
2386 		eo3.approximation = APPROXIMATION_APPROXIMATE;
2387 		if(eo2.interval_calculation >= INTERVAL_CALCULATION_INTERVAL_ARITHMETIC && containsInterval(false, true, false, -1)) factorize_variables(*this, eo3);
2388 		if(containsType(STRUCT_COMPARISON) && containsInterval(false, true, false, false)) {
2389 			eo3.approximation = APPROXIMATION_EXACT;
2390 			fix_eqs(*this, eo3);
2391 		}
2392 		eo2.approximation = APPROXIMATION_APPROXIMATE;
2393 	} else if(eo2.approximation == APPROXIMATION_EXACT && contains_function_interval(*this, false, true, false, -1)) {
2394 		EvaluationOptions eo3 = eo2;
2395 		eo3.split_squares = false;
2396 		eo3.assume_denominators_nonzero = false;
2397 		calculatesub(eo3, feo);
2398 		eo3.approximation = APPROXIMATION_APPROXIMATE;
2399 		if(eo2.interval_calculation >= INTERVAL_CALCULATION_INTERVAL_ARITHMETIC) factorize_variables(*this, eo3, true);
2400 	}
2401 	if(eo2.approximation == APPROXIMATION_EXACT) replace_function_vars(*this);
2402 
2403 	calculatesub(eo2, feo);
2404 
2405 	if(m_type == STRUCT_NUMBER) {FORMAT_COMPLEX_NUMBERS; return *this;}
2406 	if(m_type == STRUCT_UNDEFINED || m_type == STRUCT_ABORTED || m_type == STRUCT_DATETIME || m_type == STRUCT_UNIT || m_type == STRUCT_SYMBOLIC || (m_type == STRUCT_VARIABLE && !o_variable->isKnown())) return *this;
2407 	if(CALCULATOR->aborted()) return *this;
2408 
2409 	eo2.sync_units = false;
2410 	eo2.isolate_x = eo.isolate_x;
2411 
2412 	// Try isolate x without expanding expression
2413 	if(eo2.isolate_x) {
2414 		eo2.assume_denominators_nonzero = false;
2415 		if(isolate_x(eo2, feo)) {
2416 			if(CALCULATOR->aborted()) return *this;
2417 			if(eo.assume_denominators_nonzero) eo2.assume_denominators_nonzero = 2;
2418 			calculatesub(eo2, feo);
2419 		} else {
2420 			if(eo.assume_denominators_nonzero) eo2.assume_denominators_nonzero = 2;
2421 		}
2422 		if(CALCULATOR->aborted()) return *this;
2423 	}
2424 
2425 	// Try isolate x after expanding expression and perform simplification using gcd and polynomial division
2426 	if(eo.expand != 0 || (eo.test_comparisons && containsType(STRUCT_COMPARISON))) {
2427 		eo2.test_comparisons = eo.test_comparisons;
2428 		eo2.expand = eo.expand;
2429 		if(eo2.expand && (!eo.test_comparisons || !containsType(STRUCT_COMPARISON))) eo2.expand = -2;
2430 		bool b = eo2.test_comparisons;
2431 		if(!b && isAddition()) {
2432 			for(size_t i = 0; i < SIZE; i++) {
2433 				if(CHILD(i).containsType(STRUCT_ADDITION, false) == 1) {
2434 					b = true;
2435 					break;
2436 				}
2437 			}
2438 		} else if(!b) {
2439 			b = containsType(STRUCT_ADDITION, false) == 1;
2440 		}
2441 		if(b) {
2442 			calculatesub(eo2, feo);
2443 			if(CALCULATOR->aborted()) return *this;
2444 			if(eo.do_polynomial_division) do_simplification(*this, eo2, true, eo.structuring == STRUCTURING_NONE || eo.structuring == STRUCTURING_FACTORIZE, false, true, true);
2445 			if(CALCULATOR->aborted()) return *this;
2446 			if(eo2.isolate_x) {
2447 				eo2.assume_denominators_nonzero = false;
2448 				if(isolate_x(eo2, feo)) {
2449 					if(CALCULATOR->aborted()) return *this;
2450 					if(eo.assume_denominators_nonzero) eo2.assume_denominators_nonzero = 2;
2451 					calculatesub(eo2, feo);
2452 					if(containsType(STRUCT_ADDITION, false) == 1 && eo.do_polynomial_division) do_simplification(*this, eo2, true, eo.structuring == STRUCTURING_NONE || eo.structuring == STRUCTURING_FACTORIZE, false, true, true);
2453 				} else {
2454 					if(eo.assume_denominators_nonzero) eo2.assume_denominators_nonzero = 2;
2455 				}
2456 				if(CALCULATOR->aborted()) return *this;
2457 			}
2458 		}
2459 	}
2460 
2461 	// Final attempt to isolate x, by assuming denominators is non zero and testing validity afterwards
2462 	if(eo2.isolate_x && containsType(STRUCT_COMPARISON) && eo2.assume_denominators_nonzero) {
2463 		eo2.assume_denominators_nonzero = 2;
2464 		if(try_isolate_x(*this, eo2, feo)) {
2465 			if(CALCULATOR->aborted()) return *this;
2466 			calculatesub(eo2, feo);
2467 			if(containsType(STRUCT_ADDITION, false) == 1 && eo.do_polynomial_division) do_simplification(*this, eo2, true, eo.structuring == STRUCTURING_NONE || eo.structuring == STRUCTURING_FACTORIZE, false, true, true);
2468 		}
2469 	}
2470 
2471 	simplify_functions(*this, eo2, feo);
2472 
2473 	if(CALCULATOR->aborted()) return *this;
2474 
2475 	if(eo.structuring != STRUCTURING_NONE) {
2476 
2477 		if(eo.parse_options.angle_unit == ANGLE_UNIT_GRADIANS || eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES) convert_to_default_angle_unit(*this, eo);
2478 		simplify_ln(*this);
2479 		simplify_roots(*this, eo);
2480 
2481 		if(eo.keep_zero_units) remove_add_zero_unit(*this);
2482 
2483 		structure(eo.structuring, eo2, false);
2484 
2485 		simplify_ln(*this);
2486 		simplify_roots(*this, eo);
2487 
2488 	}
2489 
2490 	clean_multiplications(*this);
2491 
2492 	FORMAT_COMPLEX_NUMBERS
2493 
2494 	return *this;
2495 }
2496 
2497