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