1 /*
2     Qalculate (library)
3 
4     Copyright (C) 2003-2007, 2008, 2016-2019  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 "Calculator.h"
15 #include "MathStructure.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 <map>
23 #include <algorithm>
24 #include "MathStructure-support.h"
25 
26 using std::string;
27 using std::cout;
28 using std::vector;
29 using std::endl;
30 
mergePrecision(const MathStructure & o)31 void MathStructure::mergePrecision(const MathStructure &o) {MERGE_APPROX_AND_PREC(o)}
mergePrecision(bool approx,int prec)32 void MathStructure::mergePrecision(bool approx, int prec) {
33 	if(!b_approx && approx) setApproximate();
34 	if(prec >= 0 && (i_precision < 0 || prec < i_precision)) {
35 		setPrecision(prec);
36 	}
37 }
38 
ref()39 void MathStructure::ref() {
40 	i_ref++;
41 }
unref()42 void MathStructure::unref() {
43 	i_ref--;
44 	if(i_ref == 0) {
45 		delete this;
46 	}
47 }
refcount() const48 size_t MathStructure::refcount() const {
49 	return i_ref;
50 }
51 
52 
init()53 inline void MathStructure::init() {
54 	m_type = STRUCT_NUMBER;
55 	b_approx = false;
56 	i_precision = -1;
57 	i_ref = 1;
58 	function_value = NULL;
59 	b_protected = false;
60 	o_variable = NULL;
61 	o_function = NULL;
62 	o_unit = NULL;
63 	o_prefix = NULL;
64 	o_datetime = NULL;
65 	b_parentheses = false;
66 }
67 
MathStructure()68 MathStructure::MathStructure() {
69 	init();
70 }
MathStructure(const MathStructure & o)71 MathStructure::MathStructure(const MathStructure &o) {
72 	init();
73 	switch(o.type()) {
74 		case STRUCT_NUMBER: {
75 			o_number.set(o.number());
76 			break;
77 		}
78 		case STRUCT_ABORTED: {}
79 		case STRUCT_SYMBOLIC: {
80 			s_sym = o.symbol();
81 			break;
82 		}
83 		case STRUCT_DATETIME: {
84 			o_datetime = new QalculateDateTime(*o.datetime());
85 			break;
86 		}
87 		case STRUCT_FUNCTION: {
88 			o_function = o.function();
89 			if(o_function) o.function()->ref();
90 			if(o.functionValue()) function_value = new MathStructure(*o.functionValue());
91 			break;
92 		}
93 		case STRUCT_VARIABLE: {
94 			o_variable = o.variable();
95 			if(o_variable) o_variable->ref();
96 			break;
97 		}
98 		case STRUCT_UNIT: {
99 			o_unit = o.unit();
100 			o_prefix = o.prefix();
101 			if(o_unit) o_unit->ref();
102 			b_plural = o.isPlural();
103 			break;
104 		}
105 		case STRUCT_COMPARISON: {
106 			ct_comp = o.comparisonType();
107 			break;
108 		}
109 		default: {}
110 	}
111 	b_protected = o.isProtected();
112 	for(size_t i = 0; i < o.size(); i++) {
113 		APPEND_COPY((&o[i]))
114 	}
115 	b_approx = o.isApproximate();
116 	i_precision = o.precision();
117 	m_type = o.type();
118 	b_parentheses = o.inParentheses();
119 }
MathStructure(long int num,long int den,long int exp10)120 MathStructure::MathStructure(long int num, long int den, long int exp10) {
121 	init();
122 	o_number.set(num, den, exp10);
123 }
MathStructure(int num,int den,int exp10)124 MathStructure::MathStructure(int num, int den, int exp10) {
125 	init();
126 	o_number.set(num, den, exp10);
127 }
MathStructure(string sym,bool force_symbol)128 MathStructure::MathStructure(string sym, bool force_symbol) {
129 	init();
130 	if(!force_symbol && sym.length() > 1) {
131 		if(sym == "undefined") {
132 			setUndefined(false);
133 			return;
134 		}
135 		o_datetime = new QalculateDateTime();
136 		if(o_datetime->set(sym)) {
137 			m_type = STRUCT_DATETIME;
138 			return;
139 		}
140 		delete o_datetime;
141 		o_datetime = NULL;
142 	}
143 	s_sym = sym;
144 	m_type = STRUCT_SYMBOLIC;
145 }
MathStructure(const QalculateDateTime & o_dt)146 MathStructure::MathStructure(const QalculateDateTime &o_dt) {
147 	init();
148 	o_datetime = new QalculateDateTime(o_dt);
149 	m_type = STRUCT_DATETIME;
150 }
MathStructure(double float_value)151 MathStructure::MathStructure(double float_value) {
152 	init();
153 	o_number.setFloat(float_value);
154 	b_approx = o_number.isApproximate();
155 	i_precision = o_number.precision();
156 }
MathStructure(const MathStructure * o,...)157 MathStructure::MathStructure(const MathStructure *o, ...) {
158 	init();
159 	va_list ap;
160 	va_start(ap, o);
161 	if(o) {
162 		APPEND_COPY(o)
163 		while(true) {
164 			o = va_arg(ap, const MathStructure*);
165 			if(!o) break;
166 			APPEND_COPY(o)
167 		}
168 	}
169 	va_end(ap);
170 	m_type = STRUCT_VECTOR;
171 }
MathStructure(MathFunction * o,...)172 MathStructure::MathStructure(MathFunction *o, ...) {
173 	init();
174 	va_list ap;
175 	va_start(ap, o);
176 	o_function = o;
177 	if(o_function) o_function->ref();
178 	while(true) {
179 		const MathStructure *mstruct = va_arg(ap, const MathStructure*);
180 		if(!mstruct) break;
181 		APPEND_COPY(mstruct)
182 	}
183 	va_end(ap);
184 	m_type = STRUCT_FUNCTION;
185 }
MathStructure(Unit * u,Prefix * p)186 MathStructure::MathStructure(Unit *u, Prefix *p) {
187 	init();
188 	o_unit = u;
189 	o_prefix = p;
190 	if(o_unit) o_unit->ref();
191 	m_type = STRUCT_UNIT;
192 }
MathStructure(Variable * o)193 MathStructure::MathStructure(Variable *o) {
194 	init();
195 	o_variable = o;
196 	if(o_variable) o_variable->ref();
197 	m_type = STRUCT_VARIABLE;
198 }
MathStructure(const Number & o)199 MathStructure::MathStructure(const Number &o) {
200 	init();
201 	o_number.set(o);
202 	b_approx = o_number.isApproximate();
203 	i_precision = o_number.precision();
204 }
~MathStructure()205 MathStructure::~MathStructure() {
206 	clear();
207 }
208 
set(const MathStructure & o,bool merge_precision)209 void MathStructure::set(const MathStructure &o, bool merge_precision) {
210 	Variable *var_bak = o_variable;
211 	if(var_bak) var_bak->ref();
212 	clear(merge_precision);
213 	switch(o.type()) {
214 		case STRUCT_NUMBER: {
215 			o_number.set(o.number());
216 			break;
217 		}
218 		case STRUCT_ABORTED: {}
219 		case STRUCT_SYMBOLIC: {
220 			s_sym = o.symbol();
221 			break;
222 		}
223 		case STRUCT_DATETIME: {
224 			o_datetime = new QalculateDateTime(*o.datetime());
225 			break;
226 		}
227 		case STRUCT_FUNCTION: {
228 			o_function = o.function();
229 			if(o_function) o.function()->ref();
230 			if(o.functionValue()) function_value = new MathStructure(*o.functionValue());
231 			break;
232 		}
233 		case STRUCT_VARIABLE: {
234 			o_variable = o.variable();
235 			if(o_variable) o_variable->ref();
236 			break;
237 		}
238 		case STRUCT_UNIT: {
239 			o_unit = o.unit();
240 			o_prefix = o.prefix();
241 			if(o_unit) o_unit->ref();
242 			b_plural = o.isPlural();
243 			break;
244 		}
245 		case STRUCT_COMPARISON: {
246 			ct_comp = o.comparisonType();
247 			break;
248 		}
249 		default: {}
250 	}
251 	b_protected = o.isProtected();
252 	for(size_t i = 0; i < o.size(); i++) {
253 		APPEND_COPY((&o[i]))
254 	}
255 	if(merge_precision) {
256 		MERGE_APPROX_AND_PREC(o);
257 	} else {
258 		b_approx = o.isApproximate();
259 		i_precision = o.precision();
260 	}
261 	b_parentheses = o.inParentheses();
262 	m_type = o.type();
263 	if(var_bak) var_bak->unref();
264 }
set_nocopy(MathStructure & o,bool merge_precision)265 void MathStructure::set_nocopy(MathStructure &o, bool merge_precision) {
266 	Variable *var_bak = o_variable;
267 	if(var_bak) var_bak->ref();
268 	o.ref();
269 	clear(merge_precision);
270 	switch(o.type()) {
271 		case STRUCT_NUMBER: {
272 			o_number.set(o.number());
273 			break;
274 		}
275 		case STRUCT_ABORTED: {}
276 		case STRUCT_SYMBOLIC: {
277 			s_sym = o.symbol();
278 			break;
279 		}
280 		case STRUCT_DATETIME: {
281 			o_datetime = new QalculateDateTime(*o.datetime());
282 			break;
283 		}
284 		case STRUCT_FUNCTION: {
285 			o_function = o.function();
286 			if(o_function) o_function->ref();
287 			if(o.functionValue()) {
288 				function_value = (MathStructure*) o.functionValue();
289 				function_value->ref();
290 			}
291 			break;
292 		}
293 		case STRUCT_VARIABLE: {
294 			o_variable = o.variable();
295 			if(o_variable) o_variable->ref();
296 			break;
297 		}
298 		case STRUCT_UNIT: {
299 			o_unit = o.unit();
300 			o_prefix = o.prefix();
301 			if(o_unit) o_unit->ref();
302 			b_plural = o.isPlural();
303 			break;
304 		}
305 		case STRUCT_COMPARISON: {
306 			ct_comp = o.comparisonType();
307 			break;
308 		}
309 		default: {}
310 	}
311 	b_protected = o.isProtected();
312 	for(size_t i = 0; i < o.size(); i++) {
313 		APPEND_REF((&o[i]))
314 	}
315 	if(merge_precision) {
316 		MERGE_APPROX_AND_PREC(o);
317 	} else {
318 		b_approx = o.isApproximate();
319 		i_precision = o.precision();
320 	}
321 	b_parentheses = o.inParentheses();
322 	m_type = o.type();
323 	o.unref();
324 	if(var_bak) var_bak->unref();
325 }
setToChild(size_t index,bool preserve_precision,MathStructure * mparent,size_t index_this)326 void MathStructure::setToChild(size_t index, bool preserve_precision, MathStructure *mparent, size_t index_this) {
327 	if(index > 0 && index <= SIZE) {
328 		if(mparent) {
329 			CHILD(index - 1).ref();
330 			mparent->setChild_nocopy(&CHILD(index - 1), index_this, preserve_precision);
331 		} else {
332 			set_nocopy(CHILD(index - 1), preserve_precision);
333 		}
334 	}
335 }
set(long int num,long int den,long int exp10,bool preserve_precision)336 void MathStructure::set(long int num, long int den, long int exp10, bool preserve_precision) {
337 	clear(preserve_precision);
338 	o_number.set(num, den, exp10);
339 	if(!preserve_precision) {
340 		b_approx = false;
341 		i_precision = -1;
342 	}
343 	m_type = STRUCT_NUMBER;
344 }
set(int num,int den,int exp10,bool preserve_precision)345 void MathStructure::set(int num, int den, int exp10, bool preserve_precision) {
346 	clear(preserve_precision);
347 	o_number.set(num, den, exp10);
348 	if(!preserve_precision) {
349 		b_approx = false;
350 		i_precision = -1;
351 	}
352 	m_type = STRUCT_NUMBER;
353 }
set(double float_value,bool preserve_precision)354 void MathStructure::set(double float_value, bool preserve_precision) {
355 	clear(preserve_precision);
356 	o_number.setFloat(float_value);
357 	if(preserve_precision) {
358 		MERGE_APPROX_AND_PREC(o_number);
359 	} else {
360 		b_approx = o_number.isApproximate();
361 		i_precision = o_number.precision();
362 	}
363 	m_type = STRUCT_NUMBER;
364 }
set(string sym,bool preserve_precision,bool force_symbol)365 void MathStructure::set(string sym, bool preserve_precision, bool force_symbol) {
366 	clear(preserve_precision);
367 	if(!force_symbol && sym.length() > 1) {
368 		if(sym == "undefined") {
369 			setUndefined(true);
370 			return;
371 		}
372 		o_datetime = new QalculateDateTime();
373 		if(o_datetime->set(sym)) {
374 			m_type = STRUCT_DATETIME;
375 			return;
376 		}
377 		delete o_datetime;
378 		o_datetime = NULL;
379 	}
380 	s_sym = sym;
381 	m_type = STRUCT_SYMBOLIC;
382 }
set(const QalculateDateTime & o_dt,bool preserve_precision)383 void MathStructure::set(const QalculateDateTime &o_dt, bool preserve_precision) {
384 	clear(preserve_precision);
385 	o_datetime = new QalculateDateTime(o_dt);
386 	m_type = STRUCT_DATETIME;
387 }
setVector(const MathStructure * o,...)388 void MathStructure::setVector(const MathStructure *o, ...) {
389 	clear();
390 	va_list ap;
391 	va_start(ap, o);
392 	if(o) {
393 		APPEND_COPY(o)
394 		while(true) {
395 			o = va_arg(ap, const MathStructure*);
396 			if(!o) break;
397 			APPEND_COPY(o)
398 		}
399 	}
400 	va_end(ap);
401 	m_type = STRUCT_VECTOR;
402 }
set(MathFunction * o,...)403 void MathStructure::set(MathFunction *o, ...) {
404 	clear();
405 	va_list ap;
406 	va_start(ap, o);
407 	o_function = o;
408 	if(o_function) o_function->ref();
409 	while(true) {
410 		const MathStructure *mstruct = va_arg(ap, const MathStructure*);
411 		if(!mstruct) break;
412 		APPEND_COPY(mstruct)
413 	}
414 	va_end(ap);
415 	m_type = STRUCT_FUNCTION;
416 }
set(Unit * u,Prefix * p,bool preserve_precision)417 void MathStructure::set(Unit *u, Prefix *p, bool preserve_precision) {
418 	clear(preserve_precision);
419 	o_unit = u;
420 	o_prefix = p;
421 	if(o_unit) o_unit->ref();
422 	m_type = STRUCT_UNIT;
423 }
set(Variable * o,bool preserve_precision)424 void MathStructure::set(Variable *o, bool preserve_precision) {
425 	clear(preserve_precision);
426 	o_variable = o;
427 	if(o_variable) o_variable->ref();
428 	m_type = STRUCT_VARIABLE;
429 }
set(const Number & o,bool preserve_precision)430 void MathStructure::set(const Number &o, bool preserve_precision) {
431 	clear(preserve_precision);
432 	o_number.set(o);
433 	if(preserve_precision) {
434 		MERGE_APPROX_AND_PREC(o_number);
435 	} else {
436 		b_approx = o_number.isApproximate();
437 		i_precision = o_number.precision();
438 	}
439 	m_type = STRUCT_NUMBER;
440 }
setUndefined(bool preserve_precision)441 void MathStructure::setUndefined(bool preserve_precision) {
442 	clear(preserve_precision);
443 	m_type = STRUCT_UNDEFINED;
444 }
setAborted(bool preserve_precision)445 void MathStructure::setAborted(bool preserve_precision) {
446 	clear(preserve_precision);
447 	m_type = STRUCT_ABORTED;
448 	s_sym = _("aborted");
449 }
450 
setProtected(bool do_protect)451 void MathStructure::setProtected(bool do_protect) {b_protected = do_protect;}
isProtected() const452 bool MathStructure::isProtected() const {return b_protected;}
453 
operator =(const MathStructure & o)454 void MathStructure::operator = (const MathStructure &o) {set(o);}
operator =(const Number & o)455 void MathStructure::operator = (const Number &o) {set(o);}
operator =(int i)456 void MathStructure::operator = (int i) {set(i, 1, 0);}
operator =(Unit * u)457 void MathStructure::operator = (Unit *u) {set(u);}
operator =(Variable * v)458 void MathStructure::operator = (Variable *v) {set(v);}
operator =(string sym)459 void MathStructure::operator = (string sym) {set(sym);}
operator -() const460 MathStructure MathStructure::operator - () const {
461 	MathStructure o2(*this);
462 	o2.negate();
463 	return o2;
464 }
operator *(const MathStructure & o) const465 MathStructure MathStructure::operator * (const MathStructure &o) const {
466 	MathStructure o2(*this);
467 	o2.multiply(o);
468 	return o2;
469 }
operator /(const MathStructure & o) const470 MathStructure MathStructure::operator / (const MathStructure &o) const {
471 	MathStructure o2(*this);
472 	o2.divide(o);
473 	return o2;
474 }
operator +(const MathStructure & o) const475 MathStructure MathStructure::operator + (const MathStructure &o) const {
476 	MathStructure o2(*this);
477 	o2.add(o);
478 	return o;
479 }
operator -(const MathStructure & o) const480 MathStructure MathStructure::operator - (const MathStructure &o) const {
481 	MathStructure o2(*this);
482 	o2.subtract(o);
483 	return o2;
484 }
operator ^(const MathStructure & o) const485 MathStructure MathStructure::operator ^ (const MathStructure &o) const {
486 	MathStructure o2(*this);
487 	o2.raise(o);
488 	return o2;
489 }
operator &&(const MathStructure & o) const490 MathStructure MathStructure::operator && (const MathStructure &o) const {
491 	MathStructure o2(*this);
492 	o2.add(o, OPERATION_LOGICAL_AND);
493 	return o2;
494 }
operator ||(const MathStructure & o) const495 MathStructure MathStructure::operator || (const MathStructure &o) const {
496 	MathStructure o2(*this);
497 	o2.add(o, OPERATION_LOGICAL_OR);
498 	return o2;
499 }
operator !() const500 MathStructure MathStructure::operator ! () const {
501 	MathStructure o2(*this);
502 	o2.setLogicalNot();
503 	return o2;
504 }
505 
operator *=(const MathStructure & o)506 void MathStructure::operator *= (const MathStructure &o) {multiply(o);}
operator /=(const MathStructure & o)507 void MathStructure::operator /= (const MathStructure &o) {divide(o);}
operator +=(const MathStructure & o)508 void MathStructure::operator += (const MathStructure &o) {add(o);}
operator -=(const MathStructure & o)509 void MathStructure::operator -= (const MathStructure &o) {subtract(o);}
operator ^=(const MathStructure & o)510 void MathStructure::operator ^= (const MathStructure &o) {raise(o);}
511 
operator *=(const Number & o)512 void MathStructure::operator *= (const Number &o) {multiply(o);}
operator /=(const Number & o)513 void MathStructure::operator /= (const Number &o) {divide(o);}
operator +=(const Number & o)514 void MathStructure::operator += (const Number &o) {add(o);}
operator -=(const Number & o)515 void MathStructure::operator -= (const Number &o) {subtract(o);}
operator ^=(const Number & o)516 void MathStructure::operator ^= (const Number &o) {raise(o);}
517 
operator *=(int i)518 void MathStructure::operator *= (int i) {multiply(i);}
operator /=(int i)519 void MathStructure::operator /= (int i) {divide(i);}
operator +=(int i)520 void MathStructure::operator += (int i) {add(i);}
operator -=(int i)521 void MathStructure::operator -= (int i) {subtract(i);}
operator ^=(int i)522 void MathStructure::operator ^= (int i) {raise(i);}
523 
operator *=(Unit * u)524 void MathStructure::operator *= (Unit *u) {multiply(u);}
operator /=(Unit * u)525 void MathStructure::operator /= (Unit *u) {divide(u);}
operator +=(Unit * u)526 void MathStructure::operator += (Unit *u) {add(u);}
operator -=(Unit * u)527 void MathStructure::operator -= (Unit *u) {subtract(u);}
operator ^=(Unit * u)528 void MathStructure::operator ^= (Unit *u) {raise(u);}
529 
operator *=(Variable * v)530 void MathStructure::operator *= (Variable *v) {multiply(v);}
operator /=(Variable * v)531 void MathStructure::operator /= (Variable *v) {divide(v);}
operator +=(Variable * v)532 void MathStructure::operator += (Variable *v) {add(v);}
operator -=(Variable * v)533 void MathStructure::operator -= (Variable *v) {subtract(v);}
operator ^=(Variable * v)534 void MathStructure::operator ^= (Variable *v) {raise(v);}
535 
operator *=(string sym)536 void MathStructure::operator *= (string sym) {multiply(sym);}
operator /=(string sym)537 void MathStructure::operator /= (string sym) {divide(sym);}
operator +=(string sym)538 void MathStructure::operator += (string sym) {add(sym);}
operator -=(string sym)539 void MathStructure::operator -= (string sym) {subtract(sym);}
operator ^=(string sym)540 void MathStructure::operator ^= (string sym) {raise(sym);}
541 
operator ==(const MathStructure & o) const542 bool MathStructure::operator == (const MathStructure &o) const {return equals(o);}
operator ==(const Number & o) const543 bool MathStructure::operator == (const Number &o) const {return equals(o);}
operator ==(int i) const544 bool MathStructure::operator == (int i) const {return equals(i);}
operator ==(Unit * u) const545 bool MathStructure::operator == (Unit *u) const {return equals(u);}
operator ==(Variable * v) const546 bool MathStructure::operator == (Variable *v) const {return equals(v);}
operator ==(string sym) const547 bool MathStructure::operator == (string sym) const {return equals(sym);}
548 
operator !=(const MathStructure & o) const549 bool MathStructure::operator != (const MathStructure &o) const {return !equals(o);}
550 
operator [](size_t index) const551 const MathStructure &MathStructure::operator [] (size_t index) const {return CHILD(index);}
operator [](size_t index)552 MathStructure &MathStructure::operator [] (size_t index) {return CHILD(index);}
553 
last()554 MathStructure &MathStructure::last() {return LAST;}
last() const555 const MathStructure MathStructure::last() const {return LAST;}
556 
clear(bool preserve_precision)557 void MathStructure::clear(bool preserve_precision) {
558 	m_type = STRUCT_NUMBER;
559 	o_number.clear();
560 	if(function_value) {
561 		function_value->unref();
562 		function_value = NULL;
563 	}
564 	if(o_function) o_function->unref();
565 	o_function = NULL;
566 	if(o_variable) o_variable->unref();
567 	o_variable = NULL;
568 	if(o_unit) o_unit->unref();
569 	o_unit = NULL;
570 	if(o_datetime) delete o_datetime;
571 	o_datetime = NULL;
572 	o_prefix = NULL;
573 	b_plural = false;
574 	b_protected = false;
575 	CLEAR;
576 	if(!preserve_precision) {
577 		i_precision = -1;
578 		b_approx = false;
579 	}
580 }
clearVector(bool preserve_precision)581 void MathStructure::clearVector(bool preserve_precision) {
582 	clear(preserve_precision);
583 	m_type = STRUCT_VECTOR;
584 }
clearMatrix(bool preserve_precision)585 void MathStructure::clearMatrix(bool preserve_precision) {
586 	clearVector(preserve_precision);
587 	MathStructure *mstruct = new MathStructure();
588 	mstruct->clearVector();
589 	APPEND_POINTER(mstruct);
590 }
591 
functionValue() const592 const MathStructure *MathStructure::functionValue() const {
593 	return function_value;
594 }
595 
number() const596 const Number &MathStructure::number() const {
597 	return o_number;
598 }
number()599 Number &MathStructure::number() {
600 	return o_number;
601 }
numberUpdated()602 void MathStructure::numberUpdated() {
603 	if(m_type != STRUCT_NUMBER) return;
604 	MERGE_APPROX_AND_PREC(o_number)
605 }
childUpdated(size_t index,bool recursive)606 void MathStructure::childUpdated(size_t index, bool recursive) {
607 	if(index > SIZE || index < 1) return;
608 	if(recursive) CHILD(index - 1).childrenUpdated(true);
609 	MERGE_APPROX_AND_PREC(CHILD(index - 1))
610 }
childrenUpdated(bool recursive)611 void MathStructure::childrenUpdated(bool recursive) {
612 	for(size_t i = 0; i < SIZE; i++) {
613 		if(recursive) CHILD(i).childrenUpdated(true);
614 		MERGE_APPROX_AND_PREC(CHILD(i))
615 	}
616 }
symbol() const617 const string &MathStructure::symbol() const {
618 	return s_sym;
619 }
datetime() const620 const QalculateDateTime *MathStructure::datetime() const {
621 	return o_datetime;
622 }
datetime()623 QalculateDateTime *MathStructure::datetime() {
624 	return o_datetime;
625 }
comparisonType() const626 ComparisonType MathStructure::comparisonType() const {
627 	return ct_comp;
628 }
setComparisonType(ComparisonType comparison_type)629 void MathStructure::setComparisonType(ComparisonType comparison_type) {
630 	ct_comp = comparison_type;
631 }
setType(StructureType mtype)632 void MathStructure::setType(StructureType mtype) {
633 	m_type = mtype;
634 	if(m_type != STRUCT_FUNCTION) {
635 		if(function_value) {
636 			function_value->unref();
637 			function_value = NULL;
638 		}
639 		if(o_function) o_function->unref();
640 		o_function = NULL;
641 	}
642 	if(m_type != STRUCT_VARIABLE && o_variable) {o_variable->unref(); o_variable = NULL;}
643 	if(m_type != STRUCT_UNIT && o_unit) {o_unit->unref(); o_unit = NULL; o_prefix = NULL;}
644 	if(m_type != STRUCT_DATETIME && o_datetime) {delete o_datetime; o_datetime = NULL;}
645 }
unit() const646 Unit *MathStructure::unit() const {
647 	return o_unit;
648 }
unit_exp_unit() const649 Unit *MathStructure::unit_exp_unit() const {
650 	if(isUnit()) return o_unit;
651 	if(isPower() && CHILD(0).isUnit()) return CHILD(0).unit();
652 	return NULL;
653 }
prefix() const654 Prefix *MathStructure::prefix() const {
655 	return o_prefix;
656 }
unit_exp_prefix() const657 Prefix *MathStructure::unit_exp_prefix() const {
658 	if(isUnit()) return o_prefix;
659 	if(isPower() && CHILD(0).isUnit()) return CHILD(0).prefix();
660 	return NULL;
661 }
setPrefix(Prefix * p)662 void MathStructure::setPrefix(Prefix *p) {
663 	if(isUnit()) {
664 		o_prefix = p;
665 	}
666 }
isPlural() const667 bool MathStructure::isPlural() const {
668 	return b_plural;
669 }
setPlural(bool is_plural)670 void MathStructure::setPlural(bool is_plural) {
671 	if(isUnit()) b_plural = is_plural;
672 }
setFunction(MathFunction * f)673 void MathStructure::setFunction(MathFunction *f) {
674 	if(f) f->ref();
675 	if(o_function) o_function->unref();
676 	o_function = f;
677 }
setFunctionId(int id)678 void MathStructure::setFunctionId(int id) {
679 	setFunction(CALCULATOR->getFunctionById(id));
680 }
setUnit(Unit * u)681 void MathStructure::setUnit(Unit *u) {
682 	if(u) u->ref();
683 	if(o_unit) o_unit->unref();
684 	o_unit = u;
685 }
setVariable(Variable * v)686 void MathStructure::setVariable(Variable *v) {
687 	if(v) v->ref();
688 	if(o_variable) o_variable->unref();
689 	o_variable = v;
690 }
function() const691 MathFunction *MathStructure::function() const {
692 	return o_function;
693 }
variable() const694 Variable *MathStructure::variable() const {
695 	return o_variable;
696 }
697 
isAddition() const698 bool MathStructure::isAddition() const {return m_type == STRUCT_ADDITION;}
isMultiplication() const699 bool MathStructure::isMultiplication() const {return m_type == STRUCT_MULTIPLICATION;}
isPower() const700 bool MathStructure::isPower() const {return m_type == STRUCT_POWER;}
isSymbolic() const701 bool MathStructure::isSymbolic() const {return m_type == STRUCT_SYMBOLIC;}
isDateTime() const702 bool MathStructure::isDateTime() const {return m_type == STRUCT_DATETIME;}
isAborted() const703 bool MathStructure::isAborted() const {return m_type == STRUCT_ABORTED;}
isEmptySymbol() const704 bool MathStructure::isEmptySymbol() const {return m_type == STRUCT_SYMBOLIC && s_sym.empty();}
isVector() const705 bool MathStructure::isVector() const {return m_type == STRUCT_VECTOR;}
isMatrix() const706 bool MathStructure::isMatrix() const {
707 	if(m_type != STRUCT_VECTOR || SIZE < 1 || CHILD(0).size() == 0) return false;
708 	for(size_t i = 0; i < SIZE; i++) {
709 		if(!CHILD(i).isVector() || (i > 0 && CHILD(i).size() != CHILD(i - 1).size())) return false;
710 	}
711 	return true;
712 }
isFunction() const713 bool MathStructure::isFunction() const {return m_type == STRUCT_FUNCTION;}
isUnit() const714 bool MathStructure::isUnit() const {return m_type == STRUCT_UNIT;}
isUnit_exp() const715 bool MathStructure::isUnit_exp() const {return m_type == STRUCT_UNIT || (m_type == STRUCT_POWER && CHILD(0).isUnit());}
isUnknown() const716 bool MathStructure::isUnknown() const {return m_type == STRUCT_SYMBOLIC || (m_type == STRUCT_VARIABLE && o_variable && !o_variable->isKnown());}
isUnknown_exp() const717 bool MathStructure::isUnknown_exp() const {return isUnknown() || (m_type == STRUCT_POWER && CHILD(0).isUnknown());}
isNumber_exp() const718 bool MathStructure::isNumber_exp() const {return m_type == STRUCT_NUMBER || (m_type == STRUCT_POWER && CHILD(0).isNumber());}
isVariable() const719 bool MathStructure::isVariable() const {return m_type == STRUCT_VARIABLE;}
isComparison() const720 bool MathStructure::isComparison() const {return m_type == STRUCT_COMPARISON;}
isLogicalAnd() const721 bool MathStructure::isLogicalAnd() const {return m_type == STRUCT_LOGICAL_AND;}
isLogicalOr() const722 bool MathStructure::isLogicalOr() const {return m_type == STRUCT_LOGICAL_OR;}
isLogicalXor() const723 bool MathStructure::isLogicalXor() const {return m_type == STRUCT_LOGICAL_XOR;}
isLogicalNot() const724 bool MathStructure::isLogicalNot() const {return m_type == STRUCT_LOGICAL_NOT;}
isBitwiseAnd() const725 bool MathStructure::isBitwiseAnd() const {return m_type == STRUCT_BITWISE_AND;}
isBitwiseOr() const726 bool MathStructure::isBitwiseOr() const {return m_type == STRUCT_BITWISE_OR;}
isBitwiseXor() const727 bool MathStructure::isBitwiseXor() const {return m_type == STRUCT_BITWISE_XOR;}
isBitwiseNot() const728 bool MathStructure::isBitwiseNot() const {return m_type == STRUCT_BITWISE_NOT;}
isInverse() const729 bool MathStructure::isInverse() const {return m_type == STRUCT_INVERSE;}
isDivision() const730 bool MathStructure::isDivision() const {return m_type == STRUCT_DIVISION;}
isNegate() const731 bool MathStructure::isNegate() const {return m_type == STRUCT_NEGATE;}
isInfinity() const732 bool MathStructure::isInfinity() const {return m_type == STRUCT_NUMBER && o_number.isInfinite(true);}
isUndefined() const733 bool MathStructure::isUndefined() const {return m_type == STRUCT_UNDEFINED || (m_type == STRUCT_NUMBER && o_number.isUndefined()) || (m_type == STRUCT_VARIABLE && o_variable == CALCULATOR->getVariableById(VARIABLE_ID_UNDEFINED));}
isInteger() const734 bool MathStructure::isInteger() const {return m_type == STRUCT_NUMBER && o_number.isInteger();}
isInfinite(bool ignore_imag) const735 bool MathStructure::isInfinite(bool ignore_imag) const {return m_type == STRUCT_NUMBER && o_number.isInfinite(ignore_imag);}
isNumber() const736 bool MathStructure::isNumber() const {return m_type == STRUCT_NUMBER;}
isZero() const737 bool MathStructure::isZero() const {return m_type == STRUCT_NUMBER && o_number.isZero();}
isApproximatelyZero() const738 bool MathStructure::isApproximatelyZero() const {return m_type == STRUCT_NUMBER && !o_number.isNonZero();}
isOne() const739 bool MathStructure::isOne() const {return m_type == STRUCT_NUMBER && o_number.isOne();}
isMinusOne() const740 bool MathStructure::isMinusOne() const {return m_type == STRUCT_NUMBER && o_number.isMinusOne();}
741 
hasNegativeSign() const742 bool MathStructure::hasNegativeSign() const {
743 	return (m_type == STRUCT_NUMBER && o_number.hasNegativeSign()) || m_type == STRUCT_NEGATE || (m_type == STRUCT_MULTIPLICATION && SIZE > 0 && CHILD(0).hasNegativeSign());
744 }
745 
representsBoolean() const746 bool MathStructure::representsBoolean() const {
747 	switch(m_type) {
748 		case STRUCT_NUMBER: {return o_number.isOne() || o_number.isZero();}
749 		case STRUCT_VARIABLE: {return o_variable->representsBoolean();}
750 		case STRUCT_FUNCTION: {return (function_value && function_value->representsBoolean()) || o_function->representsBoolean(*this);}
751 		case STRUCT_MULTIPLICATION: {
752 			for(size_t i = 0; i < SIZE; i++) {
753 				if(!CHILD(i).representsBoolean()) return false;
754 			}
755 			return true;
756 		}
757 		case STRUCT_LOGICAL_NOT: {}
758 		case STRUCT_LOGICAL_AND: {}
759 		case STRUCT_LOGICAL_OR: {}
760 		case STRUCT_LOGICAL_XOR: {}
761 		case STRUCT_COMPARISON: {return true;}
762 		default: {return false;}
763 	}
764 }
765 
representsNumber(bool allow_units) const766 bool MathStructure::representsNumber(bool allow_units) const {
767 	switch(m_type) {
768 		case STRUCT_NUMBER: {return !o_number.includesInfinity();}
769 		case STRUCT_VARIABLE: {return o_variable->representsNumber(allow_units);}
770 		case STRUCT_SYMBOLIC: {return CALCULATOR->defaultAssumptions()->isNumber();}
771 		case STRUCT_FUNCTION: {return (function_value && function_value->representsNumber(allow_units)) || o_function->representsNumber(*this, allow_units);}
772 		case STRUCT_UNIT: {return allow_units;}
773 		case STRUCT_DATETIME: {return allow_units;}
774 		case STRUCT_POWER: {
775 			if(!CHILD(0).representsNonZero(allow_units) && !CHILD(1).representsPositive(allow_units)) return false;
776 		}
777 		case STRUCT_ADDITION: {}
778 		case STRUCT_MULTIPLICATION: {
779 			for(size_t i = 0; i < SIZE; i++) {
780 				if(!CHILD(i).representsNumber(allow_units)) return false;
781 			}
782 			return true;
783 		}
784 		default: {return false;}
785 	}
786 }
representsInteger(bool allow_units) const787 bool MathStructure::representsInteger(bool allow_units) const {
788 	switch(m_type) {
789 		case STRUCT_NUMBER: {return o_number.isInteger();}
790 		case STRUCT_VARIABLE: {return o_variable->representsInteger(allow_units);}
791 		case STRUCT_SYMBOLIC: {return CALCULATOR->defaultAssumptions()->isInteger();}
792 		case STRUCT_FUNCTION: {return (function_value && function_value->representsInteger(allow_units)) || o_function->representsInteger(*this, allow_units);}
793 		case STRUCT_UNIT: {return allow_units;}
794 		case STRUCT_ADDITION: {}
795 		case STRUCT_MULTIPLICATION: {
796 			for(size_t i = 0; i < SIZE; i++) {
797 				if(!CHILD(i).representsInteger(allow_units)) return false;
798 			}
799 			return true;
800 		}
801 		case STRUCT_POWER: {
802 			return CHILD(0).representsInteger(allow_units) && CHILD(1).representsInteger(false) && CHILD(1).representsPositive(false);
803 		}
804 		default: {return false;}
805 	}
806 }
representsNonInteger(bool allow_units) const807 bool MathStructure::representsNonInteger(bool allow_units) const {
808 	switch(m_type) {
809 		case STRUCT_NUMBER: {return !o_number.isInteger();}
810 		case STRUCT_VARIABLE: {return o_variable->representsNonInteger(allow_units);}
811 		case STRUCT_FUNCTION: {return (function_value && function_value->representsNonInteger(allow_units));}
812 		case STRUCT_UNIT: {return false;}
813 		case STRUCT_ADDITION: {}
814 		case STRUCT_MULTIPLICATION: {
815 			return false;
816 		}
817 		case STRUCT_POWER: {
818 			return false;
819 		}
820 		default: {return false;}
821 	}
822 }
representsFraction(bool allow_units) const823 bool MathStructure::representsFraction(bool allow_units) const {
824 	switch(m_type) {
825 		case STRUCT_NUMBER: {return o_number.isFraction();}
826 		case STRUCT_VARIABLE: {return o_variable->representsFraction(allow_units);}
827 		case STRUCT_FUNCTION: {return (function_value && function_value->representsFraction(allow_units));}
828 		case STRUCT_UNIT: {return false;}
829 		case STRUCT_ADDITION: {}
830 		case STRUCT_MULTIPLICATION: {
831 			return false;
832 		}
833 		case STRUCT_POWER: {
834 			return false;
835 		}
836 		default: {return false;}
837 	}
838 }
representsPositive(bool allow_units) const839 bool MathStructure::representsPositive(bool allow_units) const {
840 	switch(m_type) {
841 		case STRUCT_NUMBER: {return o_number.isPositive();}
842 		case STRUCT_VARIABLE: {return o_variable->representsPositive(allow_units);}
843 		case STRUCT_SYMBOLIC: {return CALCULATOR->defaultAssumptions()->isPositive();}
844 		case STRUCT_FUNCTION: {
845 			if(o_function->id() == FUNCTION_ID_STRIP_UNITS && SIZE == 1) return CHILD(0).representsPositive(true);
846 			return (function_value && function_value->representsPositive(allow_units)) || o_function->representsPositive(*this, allow_units);
847 		}
848 		case STRUCT_UNIT: {return allow_units;}
849 		case STRUCT_ADDITION: {
850 			for(size_t i = 0; i < SIZE; i++) {
851 				if(!CHILD(i).representsPositive(allow_units)) return false;
852 			}
853 			return true;
854 		}
855 		case STRUCT_MULTIPLICATION: {
856 			bool b = true;
857 			for(size_t i = 0; i < SIZE; i++) {
858 				if(CHILD(i).representsNegative(allow_units)) {
859 					b = !b;
860 				} else if(!CHILD(i).representsPositive(allow_units)) {
861 					return false;
862 				}
863 			}
864 			return b;
865 		}
866 		case STRUCT_POWER: {
867 			return (CHILD(0).representsPositive(allow_units) && CHILD(1).representsReal(false))
868 			|| (CHILD(0).representsNonZero(allow_units) && CHILD(0).representsReal(allow_units) && CHILD(1).representsEven(false) && CHILD(1).representsInteger(false));
869 		}
870 		default: {return false;}
871 	}
872 }
representsNegative(bool allow_units) const873 bool MathStructure::representsNegative(bool allow_units) const {
874 	switch(m_type) {
875 		case STRUCT_NUMBER: {return o_number.isNegative();}
876 		case STRUCT_VARIABLE: {return o_variable->representsNegative(allow_units);}
877 		case STRUCT_SYMBOLIC: {return CALCULATOR->defaultAssumptions()->isNegative();}
878 		case STRUCT_FUNCTION: {
879 			if(o_function->id() == FUNCTION_ID_STRIP_UNITS && SIZE == 1) return CHILD(0).representsNegative(true);
880 			return (function_value && function_value->representsNegative(allow_units)) || o_function->representsNegative(*this, allow_units);
881 		}
882 		case STRUCT_UNIT: {return false;}
883 		case STRUCT_ADDITION: {
884 			for(size_t i = 0; i < SIZE; i++) {
885 				if(!CHILD(i).representsNegative(allow_units)) return false;
886 			}
887 			return true;
888 		}
889 		case STRUCT_MULTIPLICATION: {
890 			bool b = false;
891 			for(size_t i = 0; i < SIZE; i++) {
892 				if(CHILD(i).representsNegative(allow_units)) {
893 					b = !b;
894 				} else if(!CHILD(i).representsPositive(allow_units)) {
895 					return false;
896 				}
897 			}
898 			return b;
899 		}
900 		case STRUCT_POWER: {
901 			return CHILD(1).representsInteger(false) && CHILD(1).representsOdd(false) && CHILD(0).representsNegative(allow_units);
902 		}
903 		default: {return false;}
904 	}
905 }
representsNonNegative(bool allow_units) const906 bool MathStructure::representsNonNegative(bool allow_units) const {
907 	switch(m_type) {
908 		case STRUCT_NUMBER: {return o_number.isNonNegative();}
909 		case STRUCT_VARIABLE: {return o_variable->representsNonNegative(allow_units);}
910 		case STRUCT_SYMBOLIC: {return CALCULATOR->defaultAssumptions()->isNonNegative();}
911 		case STRUCT_FUNCTION: {
912 			if(o_function->id() == FUNCTION_ID_STRIP_UNITS && SIZE == 1) return CHILD(0).representsNonNegative(true);
913 			return (function_value && function_value->representsNonNegative(allow_units)) || o_function->representsNonNegative(*this, allow_units);
914 		}
915 		case STRUCT_UNIT: {return allow_units;}
916 		case STRUCT_ADDITION: {
917 			for(size_t i = 0; i < SIZE; i++) {
918 				if(!CHILD(i).representsNonNegative(allow_units)) return false;
919 			}
920 			return true;
921 		}
922 		case STRUCT_MULTIPLICATION: {
923 			bool b = true;
924 			for(size_t i = 0; i < SIZE; i++) {
925 				if(CHILD(i).representsNegative(allow_units)) {
926 					b = !b;
927 				} else if(!CHILD(i).representsNonNegative(allow_units)) {
928 					return false;
929 				}
930 			}
931 			return b;
932 		}
933 		case STRUCT_POWER: {
934 			return (CHILD(0).isZero() && CHILD(1).representsNonNegative(false))
935 			|| (CHILD(0).representsNonNegative(allow_units) && CHILD(1).representsReal(false))
936 			|| (CHILD(0).representsReal(allow_units) && CHILD(1).representsEven(false) && CHILD(1).representsInteger(false));
937 		}
938 		default: {return false;}
939 	}
940 }
representsNonPositive(bool allow_units) const941 bool MathStructure::representsNonPositive(bool allow_units) const {
942 	switch(m_type) {
943 		case STRUCT_NUMBER: {return o_number.isNonPositive();}
944 		case STRUCT_VARIABLE: {return o_variable->representsNonPositive(allow_units);}
945 		case STRUCT_SYMBOLIC: {return CALCULATOR->defaultAssumptions()->isNonPositive();}
946 		case STRUCT_FUNCTION: {
947 			if(o_function->id() == FUNCTION_ID_STRIP_UNITS && SIZE == 1) return CHILD(0).representsNonPositive(true);
948 			return (function_value && function_value->representsNonPositive(allow_units)) || o_function->representsNonPositive(*this, allow_units);
949 		}
950 		case STRUCT_UNIT: {return false;}
951 		case STRUCT_ADDITION: {
952 			for(size_t i = 0; i < SIZE; i++) {
953 				if(!CHILD(i).representsNonPositive(allow_units)) return false;
954 			}
955 			return true;
956 		}
957 		case STRUCT_MULTIPLICATION: {
958 			bool b = false;
959 			for(size_t i = 0; i < SIZE; i++) {
960 				if(CHILD(i).representsNegative(allow_units)) {
961 					b = !b;
962 				} else if(!CHILD(i).representsPositive(allow_units)) {
963 					return false;
964 				}
965 			}
966 			return b;
967 		}
968 		case STRUCT_POWER: {
969 			return (CHILD(0).isZero() && CHILD(1).representsPositive(false)) || representsNegative(allow_units);
970 		}
971 		default: {return false;}
972 	}
973 }
representsRational(bool allow_units) const974 bool MathStructure::representsRational(bool allow_units) const {
975 	switch(m_type) {
976 		case STRUCT_NUMBER: {return o_number.isRational();}
977 		case STRUCT_VARIABLE: {return o_variable->representsRational(allow_units);}
978 		case STRUCT_SYMBOLIC: {return CALCULATOR->defaultAssumptions()->isRational();}
979 		case STRUCT_FUNCTION: {
980 			if(o_function->id() == FUNCTION_ID_STRIP_UNITS && SIZE == 1) return CHILD(0).representsRational(true);
981 			return (function_value && function_value->representsRational(allow_units)) || o_function->representsRational(*this, allow_units);
982 		}
983 		case STRUCT_UNIT: {return false;}
984 		case STRUCT_ADDITION: {
985 			for(size_t i = 0; i < SIZE; i++) {
986 				if(!CHILD(i).representsRational(allow_units)) return false;
987 			}
988 			return true;
989 		}
990 		case STRUCT_MULTIPLICATION: {
991 			for(size_t i = 0; i < SIZE; i++) {
992 				if(!CHILD(i).representsRational(allow_units)) {
993 					return false;
994 				}
995 			}
996 			return true;
997 		}
998 		case STRUCT_POWER: {
999 			return CHILD(1).representsInteger(false) && CHILD(0).representsRational(allow_units) && (CHILD(0).representsPositive(allow_units) || (CHILD(0).representsNegative(allow_units) && CHILD(1).representsEven(false) && CHILD(1).representsPositive(false)));
1000 		}
1001 		default: {return false;}
1002 	}
1003 }
representsReal(bool allow_units) const1004 bool MathStructure::representsReal(bool allow_units) const {
1005 	switch(m_type) {
1006 		case STRUCT_NUMBER: {return o_number.isReal();}
1007 		case STRUCT_VARIABLE: {return o_variable->representsReal(allow_units);}
1008 		case STRUCT_SYMBOLIC: {return CALCULATOR->defaultAssumptions()->isReal();}
1009 		case STRUCT_FUNCTION: {
1010 			if(o_function->id() == FUNCTION_ID_STRIP_UNITS && SIZE == 1) return CHILD(0).representsReal(true);
1011 			return (function_value && function_value->representsReal(allow_units)) || o_function->representsReal(*this, allow_units);
1012 		}
1013 		case STRUCT_UNIT: {return allow_units;}
1014 		case STRUCT_DATETIME: {return allow_units;}
1015 		case STRUCT_ADDITION: {
1016 			for(size_t i = 0; i < SIZE; i++) {
1017 				if(!CHILD(i).representsReal(allow_units)) return false;
1018 			}
1019 			return true;
1020 		}
1021 		case STRUCT_MULTIPLICATION: {
1022 			for(size_t i = 0; i < SIZE; i++) {
1023 				if(!CHILD(i).representsReal(allow_units)) {
1024 					return false;
1025 				}
1026 			}
1027 			return true;
1028 		}
1029 		case STRUCT_POWER: {
1030 			return (CHILD(0).representsPositive(allow_units) && CHILD(1).representsReal(false))
1031 			|| (CHILD(0).representsReal(allow_units) && CHILD(1).representsInteger(false) && (CHILD(1).representsPositive(false) || CHILD(0).representsNonZero(allow_units)));
1032 		}
1033 		default: {return false;}
1034 	}
1035 }
representsNonComplex(bool allow_units) const1036 bool MathStructure::representsNonComplex(bool allow_units) const {
1037 	switch(m_type) {
1038 		case STRUCT_NUMBER: {return !o_number.hasImaginaryPart();}
1039 		case STRUCT_VARIABLE: {
1040 			if(o_variable->isKnown()) return ((KnownVariable*) o_variable)->get().representsNonComplex(allow_units);
1041 			return o_variable->representsNonComplex(allow_units);
1042 		}
1043 		case STRUCT_SYMBOLIC: {return CALCULATOR->defaultAssumptions()->isReal();}
1044 		case STRUCT_FUNCTION: {
1045 			if(o_function->id() == FUNCTION_ID_STRIP_UNITS && SIZE == 1) return CHILD(0).representsNonComplex(true);
1046 			return (function_value && function_value->representsNonComplex(allow_units)) || o_function->representsNonComplex(*this, allow_units);
1047 		}
1048 		case STRUCT_UNIT: {return allow_units;}
1049 		case STRUCT_DATETIME: {return allow_units;}
1050 		case STRUCT_ADDITION: {
1051 			for(size_t i = 0; i < SIZE; i++) {
1052 				if(!CHILD(i).representsNonComplex(allow_units)) return false;
1053 			}
1054 			return true;
1055 		}
1056 		case STRUCT_MULTIPLICATION: {
1057 			for(size_t i = 0; i < SIZE; i++) {
1058 				if(!CHILD(i).representsNonComplex(allow_units)) {
1059 					return false;
1060 				}
1061 			}
1062 			return true;
1063 		}
1064 		case STRUCT_POWER: {
1065 			return (CHILD(0).representsPositive(allow_units) && CHILD(1).representsReal(false))
1066 			|| (CHILD(0).representsReal(allow_units) && CHILD(1).representsInteger(false));
1067 		}
1068 		default: {return false;}
1069 	}
1070 }
representsComplex(bool allow_units) const1071 bool MathStructure::representsComplex(bool allow_units) const {
1072 	switch(m_type) {
1073 		case STRUCT_NUMBER: {return o_number.imaginaryPartIsNonZero();}
1074 		case STRUCT_VARIABLE: {return o_variable->representsComplex(allow_units);}
1075 		case STRUCT_SYMBOLIC: {return CALCULATOR->defaultAssumptions()->isComplex();}
1076 		case STRUCT_FUNCTION: {return (function_value && function_value->representsComplex(allow_units)) || o_function->representsComplex(*this, allow_units);}
1077 		case STRUCT_ADDITION: {
1078 			bool c = false;
1079 			for(size_t i = 0; i < SIZE; i++) {
1080 				if(CHILD(i).representsComplex(allow_units)) {
1081 					if(c) return false;
1082 					c = true;
1083 				} else if(!CHILD(i).representsReal(allow_units)) {
1084 					return false;
1085 				}
1086 			}
1087 			return c;
1088 		}
1089 		case STRUCT_MULTIPLICATION: {
1090 			bool c = false;
1091 			for(size_t i = 0; i < SIZE; i++) {
1092 				if(CHILD(i).representsComplex(allow_units)) {
1093 					if(c) return false;
1094 					c = true;
1095 				} else if(!CHILD(i).representsReal(allow_units) || !CHILD(i).representsNonZero(allow_units)) {
1096 					return false;
1097 				}
1098 			}
1099 			return c;
1100 		}
1101 		case STRUCT_UNIT: {return false;}
1102 		case STRUCT_POWER: {return CHILD(1).isNumber() && CHILD(1).number().isRational() && !CHILD(1).number().isInteger() && CHILD(0).representsNegative();}
1103 		default: {return false;}
1104 	}
1105 }
representsNonZero(bool allow_units) const1106 bool MathStructure::representsNonZero(bool allow_units) const {
1107 	switch(m_type) {
1108 		case STRUCT_NUMBER: {return o_number.isNonZero();}
1109 		case STRUCT_VARIABLE: {return o_variable->representsNonZero(allow_units);}
1110 		case STRUCT_SYMBOLIC: {return CALCULATOR->defaultAssumptions()->isNonZero();}
1111 		case STRUCT_FUNCTION: {return (function_value && function_value->representsNonZero(allow_units)) || o_function->representsNonZero(*this, allow_units);}
1112 		case STRUCT_UNIT: {return allow_units;}
1113 		case STRUCT_DATETIME: {return allow_units;}
1114 		case STRUCT_ADDITION: {
1115 			bool neg = false, started = false;
1116 			for(size_t i = 0; i < SIZE; i++) {
1117 				if((!started || neg) && CHILD(i).representsNegative(allow_units)) {
1118 					neg = true;
1119 				} else if(neg || !CHILD(i).representsPositive(allow_units)) {
1120 					return false;
1121 				}
1122 				started = true;
1123 			}
1124 			return true;
1125 		}
1126 		case STRUCT_MULTIPLICATION: {
1127 			for(size_t i = 0; i < SIZE; i++) {
1128 				if(!CHILD(i).representsNonZero(allow_units)) {
1129 					return false;
1130 				}
1131 			}
1132 			return true;
1133 		}
1134 		case STRUCT_POWER: {
1135 			return (CHILD(0).representsNonZero(allow_units) && ((CHILD(1).isNumber() && !CHILD(1).number().includesInfinity()) || (!CHILD(1).isNumber() && CHILD(1).representsNumber(true)))) || (!CHILD(0).isApproximatelyZero() && CHILD(1).representsNonPositive());
1136 		}
1137 		default: {return false;}
1138 	}
1139 }
representsZero(bool allow_units) const1140 bool MathStructure::representsZero(bool allow_units) const {
1141 	switch(m_type) {
1142 		case STRUCT_NUMBER: {return o_number.isZero();}
1143 		case STRUCT_VARIABLE: {return o_variable->isKnown() && !o_variable->representsNonZero(allow_units) && ((KnownVariable*) o_variable)->get().representsZero();}
1144 		case STRUCT_FUNCTION: {return (function_value && function_value->representsZero(allow_units));}
1145 		case STRUCT_ADDITION: {
1146 			for(size_t i = 0; i < SIZE; i++) {
1147 				if(!CHILD(i).representsZero(allow_units)) {
1148 					return false;
1149 				}
1150 			}
1151 			return true;
1152 		}
1153 		case STRUCT_MULTIPLICATION: {
1154 			for(size_t i = 0; i < SIZE; i++) {
1155 				if(CHILD(i).representsZero(allow_units)) {
1156 					return true;
1157 				}
1158 			}
1159 			return false;
1160 		}
1161 		case STRUCT_POWER: {
1162 			return CHILD(0).representsZero(allow_units) && CHILD(1).representsPositive(allow_units);
1163 		}
1164 		default: {return false;}
1165 	}
1166 }
representsApproximatelyZero(bool allow_units) const1167 bool MathStructure::representsApproximatelyZero(bool allow_units) const {
1168 	switch(m_type) {
1169 		case STRUCT_NUMBER: {return !o_number.isNonZero();}
1170 		case STRUCT_VARIABLE: {return o_variable->isKnown() && !o_variable->representsNonZero(allow_units) && ((KnownVariable*) o_variable)->get().representsApproximatelyZero();}
1171 		case STRUCT_FUNCTION: {return (function_value && function_value->representsApproximatelyZero(allow_units));}
1172 		case STRUCT_ADDITION: {
1173 			for(size_t i = 0; i < SIZE; i++) {
1174 				if(!CHILD(i).representsApproximatelyZero(allow_units)) {
1175 					return false;
1176 				}
1177 			}
1178 			return true;
1179 		}
1180 		case STRUCT_MULTIPLICATION: {
1181 			for(size_t i = 0; i < SIZE; i++) {
1182 				if(CHILD(i).representsApproximatelyZero(allow_units)) {
1183 					return true;
1184 				}
1185 			}
1186 			return false;
1187 		}
1188 		case STRUCT_POWER: {
1189 			return CHILD(0).representsApproximatelyZero(allow_units) && CHILD(1).representsPositive(allow_units);
1190 		}
1191 		default: {return false;}
1192 	}
1193 }
1194 
representsEven(bool allow_units) const1195 bool MathStructure::representsEven(bool allow_units) const {
1196 	switch(m_type) {
1197 		case STRUCT_NUMBER: {return o_number.isEven();}
1198 		case STRUCT_VARIABLE: {return o_variable->representsEven(allow_units);}
1199 		case STRUCT_FUNCTION: {return (function_value && function_value->representsEven(allow_units)) || o_function->representsEven(*this, allow_units);}
1200 		default: {return false;}
1201 	}
1202 }
representsOdd(bool allow_units) const1203 bool MathStructure::representsOdd(bool allow_units) const {
1204 	switch(m_type) {
1205 		case STRUCT_NUMBER: {return o_number.isOdd();}
1206 		case STRUCT_VARIABLE: {return o_variable->representsOdd(allow_units);}
1207 		case STRUCT_FUNCTION: {return (function_value && function_value->representsOdd(allow_units)) || o_function->representsOdd(*this, allow_units);}
1208 		default: {return false;}
1209 	}
1210 }
representsUndefined(bool include_childs,bool include_infinite,bool be_strict) const1211 bool MathStructure::representsUndefined(bool include_childs, bool include_infinite, bool be_strict) const {
1212 	switch(m_type) {
1213 		case STRUCT_NUMBER: {
1214 			if(include_infinite) {
1215 				return o_number.includesInfinity();
1216 			}
1217 			return false;
1218 		}
1219 		case STRUCT_UNDEFINED: {return true;}
1220 		case STRUCT_VARIABLE: {return o_variable->representsUndefined(include_childs, include_infinite, be_strict);}
1221 		case STRUCT_FUNCTION: {
1222 			if(o_function->id() == FUNCTION_ID_STRIP_UNITS && SIZE == 1) return CHILD(0).representsUndefined(include_childs, include_infinite, be_strict);
1223 			return (function_value && function_value->representsUndefined(include_childs, include_infinite, be_strict)) || o_function->representsUndefined(*this);
1224 		}
1225 		case STRUCT_POWER: {
1226 			if(be_strict) {
1227 				if((!CHILD(0).representsNonZero(true) && !CHILD(1).representsNonNegative(false)) || (CHILD(0).isInfinity() && !CHILD(1).representsNonZero(true))) {
1228 					return true;
1229 				}
1230 			} else {
1231 				if((CHILD(0).representsZero(true) && CHILD(1).representsNegative(false)) || (CHILD(0).isInfinity() && CHILD(1).representsZero(true))) {
1232 					return true;
1233 				}
1234 			}
1235 		}
1236 		default: {
1237 			if(include_childs) {
1238 				for(size_t i = 0; i < SIZE; i++) {
1239 					if(CHILD(i).representsUndefined(include_childs, include_infinite, be_strict)) return true;
1240 				}
1241 			}
1242 			return false;
1243 		}
1244 	}
1245 }
representsNonMatrix() const1246 bool MathStructure::representsNonMatrix() const {
1247 	switch(m_type) {
1248 		case STRUCT_VECTOR: {return !isMatrix();}
1249 		case STRUCT_POWER: {return CHILD(0).representsNonMatrix();}
1250 		case STRUCT_VARIABLE: {return o_variable->representsNonMatrix();}
1251 		case STRUCT_SYMBOLIC: {return CALCULATOR->defaultAssumptions()->isNonMatrix();}
1252 		case STRUCT_FUNCTION: {
1253 			if(o_function->id() == FUNCTION_ID_STRIP_UNITS && SIZE == 1) return CHILD(0).representsNonMatrix();
1254 			return (function_value && function_value->representsNonMatrix()) || o_function->representsNonMatrix(*this);
1255 		}
1256 		case STRUCT_INVERSE: {}
1257 		case STRUCT_NEGATE: {}
1258 		case STRUCT_DIVISION: {}
1259 		case STRUCT_MULTIPLICATION: {}
1260 		case STRUCT_ADDITION: {
1261 			for(size_t i = 0; i < SIZE; i++) {
1262 				if(!CHILD(i).representsNonMatrix()) {
1263 					return false;
1264 				}
1265 			}
1266 			return true;
1267 		}
1268 		case STRUCT_ABORTED: {
1269 			return false;
1270 		}
1271 		default: {}
1272 	}
1273 	return true;
1274 }
representsScalar() const1275 bool MathStructure::representsScalar() const {
1276 	switch(m_type) {
1277 		case STRUCT_VECTOR: {return false;}
1278 		case STRUCT_POWER: {return CHILD(0).representsScalar();}
1279 		case STRUCT_VARIABLE: {return o_variable->representsScalar();}
1280 		case STRUCT_SYMBOLIC: {return CALCULATOR->defaultAssumptions()->isNonMatrix();}
1281 		case STRUCT_FUNCTION: {
1282 			if(o_function->id() == FUNCTION_ID_STRIP_UNITS && SIZE == 1) return CHILD(0).representsScalar();
1283 			return (function_value && function_value->representsScalar()) || o_function->representsScalar(*this);
1284 		}
1285 		case STRUCT_INVERSE: {}
1286 		case STRUCT_NEGATE: {}
1287 		case STRUCT_DIVISION: {}
1288 		case STRUCT_MULTIPLICATION: {}
1289 		case STRUCT_ADDITION: {
1290 			for(size_t i = 0; i < SIZE; i++) {
1291 				if(!CHILD(i).representsScalar()) {
1292 					return false;
1293 				}
1294 			}
1295 			return true;
1296 		}
1297 		case STRUCT_ABORTED: {
1298 			return false;
1299 		}
1300 		default: {}
1301 	}
1302 	return true;
1303 }
1304 
setApproximate(bool is_approx,bool recursive)1305 void MathStructure::setApproximate(bool is_approx, bool recursive) {
1306 	b_approx = is_approx;
1307 	if(!b_approx) {
1308 		i_precision = -1;
1309 	}
1310 	if(recursive) {
1311 		if(m_type == STRUCT_NUMBER) {
1312 			o_number.setApproximate(is_approx);
1313 			if(i_precision < 0 || i_precision > o_number.precision()) i_precision = o_number.precision();
1314 		}
1315 		for(size_t i = 0; i < SIZE; i++) {
1316 			CHILD(i).setApproximate(is_approx, true);
1317 		}
1318 	}
1319 }
isApproximate() const1320 bool MathStructure::isApproximate() const {
1321 	return b_approx;
1322 }
1323 
precision() const1324 int MathStructure::precision() const {
1325 	return i_precision;
1326 }
setPrecision(int prec,bool recursive)1327 void MathStructure::setPrecision(int prec, bool recursive) {
1328 	i_precision = prec;
1329 	if(i_precision > 0) b_approx = true;
1330 	if(recursive) {
1331 		if(m_type == STRUCT_NUMBER) {
1332 			o_number.setPrecision(prec);
1333 		}
1334 		for(size_t i = 0; i < SIZE; i++) {
1335 			CHILD(i).setPrecision(prec, true);
1336 		}
1337 	}
1338 }
1339 
transform(StructureType mtype,const MathStructure & o)1340 void MathStructure::transform(StructureType mtype, const MathStructure &o) {
1341 	MathStructure *struct_o = new MathStructure(o);
1342 	MathStructure *struct_this = new MathStructure();
1343 	struct_this->set_nocopy(*this);
1344 	clear(true);
1345 	m_type = mtype;
1346 	APPEND_POINTER(struct_this);
1347 	APPEND_POINTER(struct_o);
1348 	b_parentheses = false;
1349 }
transform(StructureType mtype,const Number & o)1350 void MathStructure::transform(StructureType mtype, const Number &o) {
1351 	MathStructure *struct_this = new MathStructure();
1352 	struct_this->set_nocopy(*this);
1353 	clear(true);
1354 	m_type = mtype;
1355 	APPEND_POINTER(struct_this);
1356 	APPEND_NEW(o);
1357 	b_parentheses = false;
1358 }
transform(StructureType mtype,int i)1359 void MathStructure::transform(StructureType mtype, int i) {
1360 	MathStructure *struct_this = new MathStructure();
1361 	struct_this->set_nocopy(*this);
1362 	clear(true);
1363 	m_type = mtype;
1364 	APPEND_POINTER(struct_this);
1365 	APPEND_POINTER(new MathStructure(i, 1, 0));
1366 	b_parentheses = false;
1367 }
transform(StructureType mtype,Unit * u)1368 void MathStructure::transform(StructureType mtype, Unit *u) {
1369 	MathStructure *struct_this = new MathStructure();
1370 	struct_this->set_nocopy(*this);
1371 	clear(true);
1372 	m_type = mtype;
1373 	APPEND_POINTER(struct_this);
1374 	APPEND_NEW(u);
1375 	b_parentheses = false;
1376 }
transform(StructureType mtype,Variable * v)1377 void MathStructure::transform(StructureType mtype, Variable *v) {
1378 	MathStructure *struct_this = new MathStructure();
1379 	struct_this->set_nocopy(*this);
1380 	clear(true);
1381 	m_type = mtype;
1382 	APPEND_POINTER(struct_this);
1383 	APPEND_NEW(v);
1384 	b_parentheses = false;
1385 }
transform(StructureType mtype,string sym)1386 void MathStructure::transform(StructureType mtype, string sym) {
1387 	MathStructure *struct_this = new MathStructure();
1388 	struct_this->set_nocopy(*this);
1389 	clear(true);
1390 	m_type = mtype;
1391 	APPEND_POINTER(struct_this);
1392 	APPEND_NEW(sym);
1393 	b_parentheses = false;
1394 }
transform_nocopy(StructureType mtype,MathStructure * o)1395 void MathStructure::transform_nocopy(StructureType mtype, MathStructure *o) {
1396 	MathStructure *struct_this = new MathStructure();
1397 	struct_this->set_nocopy(*this);
1398 	clear(true);
1399 	m_type = mtype;
1400 	APPEND_POINTER(struct_this);
1401 	APPEND_POINTER(o);
1402 	b_parentheses = false;
1403 }
transform(StructureType mtype)1404 void MathStructure::transform(StructureType mtype) {
1405 	MathStructure *struct_this = new MathStructure();
1406 	struct_this->set_nocopy(*this);
1407 	clear(true);
1408 	m_type = mtype;
1409 	APPEND_POINTER(struct_this);
1410 	b_parentheses = false;
1411 }
transform(MathFunction * o)1412 void MathStructure::transform(MathFunction *o) {
1413 	transform(STRUCT_FUNCTION);
1414 	setFunction(o);
1415 	b_parentheses = false;
1416 }
transformById(int id)1417 void MathStructure::transformById(int id) {
1418 	transform(STRUCT_FUNCTION);
1419 	setFunctionId(id);
1420 	b_parentheses = false;
1421 }
transform(ComparisonType ctype,const MathStructure & o)1422 void MathStructure::transform(ComparisonType ctype, const MathStructure &o) {
1423 	MathStructure *struct_o = new MathStructure(o);
1424 	MathStructure *struct_this = new MathStructure();
1425 	struct_this->set_nocopy(*this);
1426 	clear(true);
1427 	m_type = STRUCT_COMPARISON;
1428 	ct_comp = ctype;
1429 	APPEND_POINTER(struct_this);
1430 	APPEND_POINTER(struct_o);
1431 	b_parentheses = false;
1432 }
1433 void transform(ComparisonType ctype, const MathStructure &o);
add(const MathStructure & o,MathOperation op,bool append)1434 void MathStructure::add(const MathStructure &o, MathOperation op, bool append) {
1435 	switch(op) {
1436 		case OPERATION_ADD: {
1437 			add(o, append);
1438 			break;
1439 		}
1440 		case OPERATION_SUBTRACT: {
1441 			subtract(o, append);
1442 			break;
1443 		}
1444 		case OPERATION_MULTIPLY: {
1445 			multiply(o, append);
1446 			break;
1447 		}
1448 		case OPERATION_DIVIDE: {
1449 			divide(o, append);
1450 			break;
1451 		}
1452 		case OPERATION_RAISE: {
1453 			raise(o);
1454 			break;
1455 		}
1456 		case OPERATION_EXP10: {
1457 			MathStructure *mstruct = new MathStructure(10, 1, 0);
1458 			mstruct->raise(o);
1459 			multiply_nocopy(mstruct, append);
1460 			break;
1461 		}
1462 		case OPERATION_LOGICAL_AND: {
1463 			if(m_type == STRUCT_LOGICAL_AND && append) {
1464 				APPEND(o);
1465 			} else {
1466 				transform(STRUCT_LOGICAL_AND, o);
1467 			}
1468 			break;
1469 		}
1470 		case OPERATION_LOGICAL_OR: {
1471 			if(m_type == STRUCT_LOGICAL_OR && append) {
1472 				APPEND(o);
1473 			} else {
1474 				transform(STRUCT_LOGICAL_OR, o);
1475 			}
1476 			break;
1477 		}
1478 		case OPERATION_LOGICAL_XOR: {
1479 			transform(STRUCT_LOGICAL_XOR, o);
1480 			break;
1481 		}
1482 		case OPERATION_BITWISE_AND: {
1483 			if(m_type == STRUCT_BITWISE_AND && append) {
1484 				APPEND(o);
1485 			} else {
1486 				transform(STRUCT_BITWISE_AND, o);
1487 			}
1488 			break;
1489 		}
1490 		case OPERATION_BITWISE_OR: {
1491 			if(m_type == STRUCT_BITWISE_OR && append) {
1492 				APPEND(o);
1493 			} else {
1494 				transform(STRUCT_BITWISE_OR, o);
1495 			}
1496 			break;
1497 		}
1498 		case OPERATION_BITWISE_XOR: {
1499 			transform(STRUCT_BITWISE_XOR, o);
1500 			break;
1501 		}
1502 		case OPERATION_EQUALS: {}
1503 		case OPERATION_NOT_EQUALS: {}
1504 		case OPERATION_GREATER: {}
1505 		case OPERATION_LESS: {}
1506 		case OPERATION_EQUALS_GREATER: {}
1507 		case OPERATION_EQUALS_LESS: {
1508 			if(append && m_type == STRUCT_COMPARISON) {
1509 				MathStructure *o2 = new MathStructure(CHILD(1));
1510 				o2->add(o, op);
1511 				transform_nocopy(STRUCT_LOGICAL_AND, o2);
1512 			} else if(append && m_type == STRUCT_LOGICAL_AND && LAST.type() == STRUCT_COMPARISON) {
1513 				MathStructure *o2 = new MathStructure(LAST[1]);
1514 				o2->add(o, op);
1515 				APPEND_POINTER(o2);
1516 			} else {
1517 				transform(STRUCT_COMPARISON, o);
1518 				switch(op) {
1519 					case OPERATION_EQUALS: {ct_comp = COMPARISON_EQUALS; break;}
1520 					case OPERATION_NOT_EQUALS: {ct_comp = COMPARISON_NOT_EQUALS; break;}
1521 					case OPERATION_GREATER: {ct_comp = COMPARISON_GREATER; break;}
1522 					case OPERATION_LESS: {ct_comp = COMPARISON_LESS; break;}
1523 					case OPERATION_EQUALS_GREATER: {ct_comp = COMPARISON_EQUALS_GREATER; break;}
1524 					case OPERATION_EQUALS_LESS: {ct_comp = COMPARISON_EQUALS_LESS; break;}
1525 					default: {}
1526 				}
1527 			}
1528 			break;
1529 		}
1530 		default: {
1531 		}
1532 	}
1533 }
add(const MathStructure & o,bool append)1534 void MathStructure::add(const MathStructure &o, bool append) {
1535 	if(m_type == STRUCT_ADDITION && append) {
1536 		APPEND(o);
1537 	} else {
1538 		transform(STRUCT_ADDITION, o);
1539 	}
1540 }
subtract(const MathStructure & o,bool append)1541 void MathStructure::subtract(const MathStructure &o, bool append) {
1542 	MathStructure *o2 = new MathStructure(o);
1543 	o2->negate();
1544 	add_nocopy(o2, append);
1545 }
multiply(const MathStructure & o,bool append)1546 void MathStructure::multiply(const MathStructure &o, bool append) {
1547 	if(m_type == STRUCT_MULTIPLICATION && append) {
1548 		APPEND(o);
1549 	} else {
1550 		transform(STRUCT_MULTIPLICATION, o);
1551 	}
1552 }
divide(const MathStructure & o,bool append)1553 void MathStructure::divide(const MathStructure &o, bool append) {
1554 //	transform(STRUCT_DIVISION, o);
1555 	MathStructure *o2 = new MathStructure(o);
1556 	o2->inverse();
1557 	multiply_nocopy(o2, append);
1558 }
raise(const MathStructure & o)1559 void MathStructure::raise(const MathStructure &o) {
1560 	transform(STRUCT_POWER, o);
1561 }
add(const Number & o,bool append)1562 void MathStructure::add(const Number &o, bool append) {
1563 	if(m_type == STRUCT_ADDITION && append) {
1564 		APPEND_NEW(o);
1565 	} else {
1566 		transform(STRUCT_ADDITION, o);
1567 	}
1568 }
subtract(const Number & o,bool append)1569 void MathStructure::subtract(const Number &o, bool append) {
1570 	MathStructure *o2 = new MathStructure(o);
1571 	o2->negate();
1572 	add_nocopy(o2, append);
1573 }
multiply(const Number & o,bool append)1574 void MathStructure::multiply(const Number &o, bool append) {
1575 	if(m_type == STRUCT_MULTIPLICATION && append) {
1576 		APPEND_NEW(o);
1577 	} else {
1578 		transform(STRUCT_MULTIPLICATION, o);
1579 	}
1580 }
divide(const Number & o,bool append)1581 void MathStructure::divide(const Number &o, bool append) {
1582 	MathStructure *o2 = new MathStructure(o);
1583 	o2->inverse();
1584 	multiply_nocopy(o2, append);
1585 }
raise(const Number & o)1586 void MathStructure::raise(const Number &o) {
1587 	transform(STRUCT_POWER, o);
1588 }
add(int i,bool append)1589 void MathStructure::add(int i, bool append) {
1590 	if(m_type == STRUCT_ADDITION && append) {
1591 		APPEND_POINTER(new MathStructure(i, 1, 0));
1592 	} else {
1593 		transform(STRUCT_ADDITION, i);
1594 	}
1595 }
subtract(int i,bool append)1596 void MathStructure::subtract(int i, bool append) {
1597 	MathStructure *o2 = new MathStructure(i, 1, 0);
1598 	o2->negate();
1599 	add_nocopy(o2, append);
1600 }
multiply(int i,bool append)1601 void MathStructure::multiply(int i, bool append) {
1602 	if(m_type == STRUCT_MULTIPLICATION && append) {
1603 		APPEND_POINTER(new MathStructure(i, 1, 0));
1604 	} else {
1605 		transform(STRUCT_MULTIPLICATION, i);
1606 	}
1607 }
divide(int i,bool append)1608 void MathStructure::divide(int i, bool append) {
1609 	MathStructure *o2 = new MathStructure(i, 1, 0);
1610 	o2->inverse();
1611 	multiply_nocopy(o2, append);
1612 }
raise(int i)1613 void MathStructure::raise(int i) {
1614 	transform(STRUCT_POWER, i);
1615 }
add(Variable * v,bool append)1616 void MathStructure::add(Variable *v, bool append) {
1617 	if(m_type == STRUCT_ADDITION && append) {
1618 		APPEND_NEW(v);
1619 	} else {
1620 		transform(STRUCT_ADDITION, v);
1621 	}
1622 }
subtract(Variable * v,bool append)1623 void MathStructure::subtract(Variable *v, bool append) {
1624 	MathStructure *o2 = new MathStructure(v);
1625 	o2->negate();
1626 	add_nocopy(o2, append);
1627 }
multiply(Variable * v,bool append)1628 void MathStructure::multiply(Variable *v, bool append) {
1629 	if(m_type == STRUCT_MULTIPLICATION && append) {
1630 		APPEND_NEW(v);
1631 	} else {
1632 		transform(STRUCT_MULTIPLICATION, v);
1633 	}
1634 }
divide(Variable * v,bool append)1635 void MathStructure::divide(Variable *v, bool append) {
1636 	MathStructure *o2 = new MathStructure(v);
1637 	o2->inverse();
1638 	multiply_nocopy(o2, append);
1639 }
raise(Variable * v)1640 void MathStructure::raise(Variable *v) {
1641 	transform(STRUCT_POWER, v);
1642 }
add(Unit * u,bool append)1643 void MathStructure::add(Unit *u, bool append) {
1644 	if(m_type == STRUCT_ADDITION && append) {
1645 		APPEND_NEW(u);
1646 	} else {
1647 		transform(STRUCT_ADDITION, u);
1648 	}
1649 }
subtract(Unit * u,bool append)1650 void MathStructure::subtract(Unit *u, bool append) {
1651 	MathStructure *o2 = new MathStructure(u);
1652 	o2->negate();
1653 	add_nocopy(o2, append);
1654 }
multiply(Unit * u,bool append)1655 void MathStructure::multiply(Unit *u, bool append) {
1656 	if(m_type == STRUCT_MULTIPLICATION && append) {
1657 		APPEND_NEW(u);
1658 	} else {
1659 		transform(STRUCT_MULTIPLICATION, u);
1660 	}
1661 }
divide(Unit * u,bool append)1662 void MathStructure::divide(Unit *u, bool append) {
1663 	MathStructure *o2 = new MathStructure(u);
1664 	o2->inverse();
1665 	multiply_nocopy(o2, append);
1666 }
raise(Unit * u)1667 void MathStructure::raise(Unit *u) {
1668 	transform(STRUCT_POWER, u);
1669 }
add(string sym,bool append)1670 void MathStructure::add(string sym, bool append) {
1671 	if(m_type == STRUCT_ADDITION && append) {
1672 		APPEND_NEW(sym);
1673 	} else {
1674 		transform(STRUCT_ADDITION, sym);
1675 	}
1676 }
subtract(string sym,bool append)1677 void MathStructure::subtract(string sym, bool append) {
1678 	MathStructure *o2 = new MathStructure(sym);
1679 	o2->negate();
1680 	add_nocopy(o2, append);
1681 }
multiply(string sym,bool append)1682 void MathStructure::multiply(string sym, bool append) {
1683 	if(m_type == STRUCT_MULTIPLICATION && append) {
1684 		APPEND_NEW(sym);
1685 	} else {
1686 		transform(STRUCT_MULTIPLICATION, sym);
1687 	}
1688 }
divide(string sym,bool append)1689 void MathStructure::divide(string sym, bool append) {
1690 	MathStructure *o2 = new MathStructure(sym);
1691 	o2->inverse();
1692 	multiply_nocopy(o2, append);
1693 }
raise(string sym)1694 void MathStructure::raise(string sym) {
1695 	transform(STRUCT_POWER, sym);
1696 }
add_nocopy(MathStructure * o,MathOperation op,bool append)1697 void MathStructure::add_nocopy(MathStructure *o, MathOperation op, bool append) {
1698 	switch(op) {
1699 		case OPERATION_ADD: {
1700 			add_nocopy(o, append);
1701 			break;
1702 		}
1703 		case OPERATION_SUBTRACT: {
1704 			subtract_nocopy(o, append);
1705 			break;
1706 		}
1707 		case OPERATION_MULTIPLY: {
1708 			multiply_nocopy(o, append);
1709 			break;
1710 		}
1711 		case OPERATION_DIVIDE: {
1712 			divide_nocopy(o, append);
1713 			break;
1714 		}
1715 		case OPERATION_RAISE: {
1716 			raise_nocopy(o);
1717 			break;
1718 		}
1719 		case OPERATION_EXP10: {
1720 			MathStructure *mstruct = new MathStructure(10, 1, 0);
1721 			mstruct->raise_nocopy(o);
1722 			multiply_nocopy(mstruct, append);
1723 			break;
1724 		}
1725 		case OPERATION_LOGICAL_AND: {
1726 			if(m_type == STRUCT_LOGICAL_AND && append) {
1727 				APPEND_POINTER(o);
1728 			} else {
1729 				transform_nocopy(STRUCT_LOGICAL_AND, o);
1730 			}
1731 			break;
1732 		}
1733 		case OPERATION_LOGICAL_OR: {
1734 			if(m_type == STRUCT_LOGICAL_OR && append) {
1735 				APPEND_POINTER(o);
1736 			} else {
1737 				transform_nocopy(STRUCT_LOGICAL_OR, o);
1738 			}
1739 			break;
1740 		}
1741 		case OPERATION_LOGICAL_XOR: {
1742 			transform_nocopy(STRUCT_LOGICAL_XOR, o);
1743 			break;
1744 		}
1745 		case OPERATION_BITWISE_AND: {
1746 			if(m_type == STRUCT_BITWISE_AND && append) {
1747 				APPEND_POINTER(o);
1748 			} else {
1749 				transform_nocopy(STRUCT_BITWISE_AND, o);
1750 			}
1751 			break;
1752 		}
1753 		case OPERATION_BITWISE_OR: {
1754 			if(m_type == STRUCT_BITWISE_OR && append) {
1755 				APPEND_POINTER(o);
1756 			} else {
1757 				transform_nocopy(STRUCT_BITWISE_OR, o);
1758 			}
1759 			break;
1760 		}
1761 		case OPERATION_BITWISE_XOR: {
1762 			transform_nocopy(STRUCT_BITWISE_XOR, o);
1763 			break;
1764 		}
1765 		case OPERATION_EQUALS: {}
1766 		case OPERATION_NOT_EQUALS: {}
1767 		case OPERATION_GREATER: {}
1768 		case OPERATION_LESS: {}
1769 		case OPERATION_EQUALS_GREATER: {}
1770 		case OPERATION_EQUALS_LESS: {
1771 			if(append && m_type == STRUCT_COMPARISON) {
1772 				MathStructure *o2 = new MathStructure(CHILD(1));
1773 				o2->add_nocopy(o, op);
1774 				transform_nocopy(STRUCT_LOGICAL_AND, o2);
1775 			} else if(append && m_type == STRUCT_LOGICAL_AND && LAST.type() == STRUCT_COMPARISON) {
1776 				MathStructure *o2 = new MathStructure(LAST[1]);
1777 				o2->add_nocopy(o, op);
1778 				APPEND_POINTER(o2);
1779 			} else {
1780 				transform_nocopy(STRUCT_COMPARISON, o);
1781 				switch(op) {
1782 					case OPERATION_EQUALS: {ct_comp = COMPARISON_EQUALS; break;}
1783 					case OPERATION_NOT_EQUALS: {ct_comp = COMPARISON_NOT_EQUALS; break;}
1784 					case OPERATION_GREATER: {ct_comp = COMPARISON_GREATER; break;}
1785 					case OPERATION_LESS: {ct_comp = COMPARISON_LESS; break;}
1786 					case OPERATION_EQUALS_GREATER: {ct_comp = COMPARISON_EQUALS_GREATER; break;}
1787 					case OPERATION_EQUALS_LESS: {ct_comp = COMPARISON_EQUALS_LESS; break;}
1788 					default: {}
1789 				}
1790 			}
1791 			break;
1792 		}
1793 		default: {
1794 		}
1795 	}
1796 }
add_nocopy(MathStructure * o,bool append)1797 void MathStructure::add_nocopy(MathStructure *o, bool append) {
1798 	if(m_type == STRUCT_ADDITION && append) {
1799 		APPEND_POINTER(o);
1800 	} else {
1801 		transform_nocopy(STRUCT_ADDITION, o);
1802 	}
1803 }
subtract_nocopy(MathStructure * o,bool append)1804 void MathStructure::subtract_nocopy(MathStructure *o, bool append) {
1805 	o->negate();
1806 	add_nocopy(o, append);
1807 }
multiply_nocopy(MathStructure * o,bool append)1808 void MathStructure::multiply_nocopy(MathStructure *o, bool append) {
1809 	if(m_type == STRUCT_MULTIPLICATION && append) {
1810 		APPEND_POINTER(o);
1811 	} else {
1812 		transform_nocopy(STRUCT_MULTIPLICATION, o);
1813 	}
1814 }
divide_nocopy(MathStructure * o,bool append)1815 void MathStructure::divide_nocopy(MathStructure *o, bool append) {
1816 	o->inverse();
1817 	multiply_nocopy(o, append);
1818 }
raise_nocopy(MathStructure * o)1819 void MathStructure::raise_nocopy(MathStructure *o) {
1820 	transform_nocopy(STRUCT_POWER, o);
1821 }
negate()1822 void MathStructure::negate() {
1823 	//transform(STRUCT_NEGATE);
1824 	MathStructure *struct_this = new MathStructure();
1825 	struct_this->set_nocopy(*this);
1826 	clear(true);
1827 	m_type = STRUCT_MULTIPLICATION;
1828 	APPEND(m_minus_one);
1829 	APPEND_POINTER(struct_this);
1830 }
inverse()1831 void MathStructure::inverse() {
1832 	//transform(STRUCT_INVERSE);
1833 	raise(m_minus_one);
1834 }
setLogicalNot()1835 void MathStructure::setLogicalNot() {
1836 	transform(STRUCT_LOGICAL_NOT);
1837 }
setBitwiseNot()1838 void MathStructure::setBitwiseNot() {
1839 	transform(STRUCT_BITWISE_NOT);
1840 }
1841 
equals(const MathStructure & o,bool allow_interval,bool allow_infinite) const1842 bool MathStructure::equals(const MathStructure &o, bool allow_interval, bool allow_infinite) const {
1843 	if(m_type != o.type()) return false;
1844 	if(SIZE != o.size()) return false;
1845 	switch(m_type) {
1846 		case STRUCT_UNDEFINED: {return true;}
1847 		case STRUCT_SYMBOLIC: {return s_sym == o.symbol();}
1848 		case STRUCT_DATETIME: {return *o_datetime == *o.datetime();}
1849 		case STRUCT_NUMBER: {return o_number.equals(o.number(), allow_interval, allow_infinite);}
1850 		case STRUCT_VARIABLE: {return o_variable == o.variable();}
1851 		case STRUCT_UNIT: {
1852 			Prefix *p1 = (o_prefix == NULL || o_prefix == CALCULATOR->getDecimalNullPrefix() || o_prefix == CALCULATOR->getBinaryNullPrefix()) ? NULL : o_prefix;
1853 			Prefix *p2 = (o.prefix() == NULL || o.prefix() == CALCULATOR->getDecimalNullPrefix() || o.prefix() == CALCULATOR->getBinaryNullPrefix()) ? NULL : o.prefix();
1854 			return o_unit == o.unit() && p1 == p2;
1855 		}
1856 		case STRUCT_COMPARISON: {if(ct_comp != o.comparisonType()) return false; break;}
1857 		case STRUCT_FUNCTION: {if(o_function != o.function()) return false; break;}
1858 		case STRUCT_LOGICAL_OR: {}
1859 		case STRUCT_LOGICAL_XOR: {}
1860 		case STRUCT_LOGICAL_AND: {
1861 			if(SIZE < 1) return false;
1862 			if(SIZE == 2) {
1863 				return (CHILD(0) == o[0] && CHILD(1) == o[1]) || (CHILD(0) == o[1] && CHILD(1) == o[0]);
1864 			}
1865 			vector<size_t> i2taken;
1866 			for(size_t i = 0; i < SIZE; i++) {
1867 				bool b = false, b2 = false;
1868 				for(size_t i2 = 0; i2 < o.size(); i2++) {
1869 					if(CHILD(i).equals(o[i2], allow_interval)) {
1870 						b2 = true;
1871 						for(size_t i3 = 0; i3 < i2taken.size(); i3++) {
1872 							if(i2taken[i3] == i2) {
1873 								b2 = false;
1874 							}
1875 						}
1876 						if(b2) {
1877 							b = true;
1878 							i2taken.push_back(i2);
1879 							break;
1880 						}
1881 					}
1882 				}
1883 				if(!b) return false;
1884 			}
1885 			return true;
1886 		}
1887 		default: {}
1888 	}
1889 	if(SIZE < 1) return false;
1890 	for(size_t i = 0; i < SIZE; i++) {
1891 		if(!CHILD(i).equals(o[i], allow_interval)) return false;
1892 	}
1893 	return true;
1894 }
equals(const Number & o,bool allow_interval,bool allow_infinite) const1895 bool MathStructure::equals(const Number &o, bool allow_interval, bool allow_infinite) const {
1896 	if(m_type != STRUCT_NUMBER) return false;
1897 	return o_number.equals(o, allow_interval, allow_infinite);
1898 }
equals(int i) const1899 bool MathStructure::equals(int i) const {
1900 	if(m_type != STRUCT_NUMBER) return false;
1901 	return o_number.equals(Number(i, 1, 0));
1902 }
equals(Unit * u) const1903 bool MathStructure::equals(Unit *u) const {
1904 	if(m_type != STRUCT_UNIT) return false;
1905 	return o_unit == u;
1906 }
equals(Variable * v) const1907 bool MathStructure::equals(Variable *v) const {
1908 	if(m_type != STRUCT_VARIABLE) return false;
1909 	return o_variable == v;
1910 }
equals(string sym) const1911 bool MathStructure::equals(string sym) const {
1912 	if(m_type != STRUCT_SYMBOLIC) return false;
1913 	return s_sym == sym;
1914 }
1915 
remove_rad_unit_cf(MathStructure & m)1916 bool remove_rad_unit_cf(MathStructure &m) {
1917 	if(m.isFunction() && m.containsType(STRUCT_UNIT, false, true, true) <= 0) return false;
1918 	for(size_t i = 0; i < m.size(); i++) {
1919 		if(!remove_rad_unit_cf(m[i])) return false;
1920 	}
1921 	return true;
1922 }
remove_rad_unit(MathStructure & m,const EvaluationOptions & eo,bool top)1923 bool remove_rad_unit(MathStructure &m, const EvaluationOptions &eo, bool top) {
1924 	if(top && !remove_rad_unit_cf(m)) return false;
1925 	if(m.isUnit()) {
1926 		if(m.unit() == CALCULATOR->getRadUnit()) {
1927 			m.set(1, 1, 0, true);
1928 			return true;
1929 		} else if(m.unit()->containsRelativeTo(CALCULATOR->getRadUnit())) {
1930 			if(m.convert(CALCULATOR->getRadUnit())) {
1931 				return remove_rad_unit(m, eo, false);
1932 			}
1933 		}
1934 	} else {
1935 		bool b = false;
1936 		for(size_t i = 0; i < m.size(); i++) {
1937 			if(remove_rad_unit(m[i], eo, false)) b = true;
1938 		}
1939 		if(b) {
1940 			m.calculatesub(eo, eo, false);
1941 			return true;
1942 		}
1943 	}
1944 	return false;
1945 }
1946 
compare_check_incompability(MathStructure * mtest)1947 int compare_check_incompability(MathStructure *mtest) {
1948 	int incomp = 0;
1949 	int unit_term_count = 0;
1950 	int not_unit_term_count = 0;
1951 	int compat_count = 0;
1952 	bool b_not_number = false;
1953 	for(size_t i = 0; i < mtest->size(); i++) {
1954 		if((*mtest)[i].containsType(STRUCT_UNIT, false, true, true) > 0) {
1955 			unit_term_count++;
1956 			for(size_t i2 = i + 1; i2 < mtest->size(); i2++) {
1957 				int b_test = (*mtest)[i].isUnitCompatible((*mtest)[i2]);
1958 				if(b_test == 0) {
1959 					incomp = 1;
1960 				} else if(b_test > 0) {
1961 					compat_count++;
1962 				}
1963 			}
1964 			if(!b_not_number && !(*mtest)[i].representsNumber(true)) {
1965 				b_not_number = true;
1966 			}
1967 		} else if((*mtest)[i].containsRepresentativeOfType(STRUCT_UNIT, true, true) == 0) {
1968 			not_unit_term_count++;
1969 		} else if(!b_not_number && !(*mtest)[i].representsNumber(true)) {
1970 			b_not_number = true;
1971 		}
1972 	}
1973 	if(b_not_number && unit_term_count > 0) {
1974 		incomp = -1;
1975 	} else if(unit_term_count > 0) {
1976 		if((long int) mtest->size() - (unit_term_count + not_unit_term_count) >= unit_term_count - compat_count + (not_unit_term_count > 0)) {
1977 			incomp = -1;
1978 		} else if(not_unit_term_count > 0) {
1979 			incomp = 1;
1980 		}
1981 	}
1982 	return incomp;
1983 }
1984 
replace_interval_unknowns(MathStructure & m,bool do_assumptions)1985 bool replace_interval_unknowns(MathStructure &m, bool do_assumptions) {
1986 	if(m.isVariable() && !m.variable()->isKnown()) {
1987 		if(!((UnknownVariable*) m.variable())->interval().isUndefined()) {
1988 			m = ((UnknownVariable*) m.variable())->interval();
1989 			replace_interval_unknowns(m, do_assumptions);
1990 			return true;
1991 		} else if(do_assumptions) {
1992 			Assumptions *ass = ((UnknownVariable*) m.variable())->assumptions();
1993 			if(ass && ((ass->sign() != ASSUMPTION_SIGN_UNKNOWN && ass->sign() != ASSUMPTION_SIGN_NONZERO) || ass->min() || ass->max())) {
1994 				Number nr_intval;
1995 				if(ass->min()) {
1996 					if(ass->max()) nr_intval.setInterval(*ass->min(), *ass->max());
1997 					else nr_intval.setInterval(*ass->min(), nr_plus_inf);
1998 				} else if(ass->max()) {
1999 					nr_intval.setInterval(nr_minus_inf, *ass->max());
2000 				} else if(ass->sign() == ASSUMPTION_SIGN_NEGATIVE || ass->sign() == ASSUMPTION_SIGN_NONPOSITIVE) {
2001 					nr_intval.setInterval(nr_minus_inf, nr_zero);
2002 				} else {
2003 					nr_intval.setInterval(nr_zero, nr_plus_inf);
2004 				}
2005 				m = nr_intval;
2006 				return true;
2007 			}
2008 		}
2009 	}
2010 	bool b = false;
2011 	for(size_t i = 0; i < m.size(); i++) {
2012 		if(replace_interval_unknowns(m[i], do_assumptions)) b = true;
2013 	}
2014 	return b;
2015 }
contains_ass_intval(const MathStructure & m)2016 int contains_ass_intval(const MathStructure &m) {
2017 	if(m.isVariable() && !m.variable()->isKnown()) {
2018 		Assumptions *ass = ((UnknownVariable*) m.variable())->assumptions();
2019 		if(ass && (ass->min() || ass->max())) return 1;
2020 		return 0;
2021 	}
2022 	int b = 0;
2023 	for(size_t i = 0; i < m.size(); i++) {
2024 		int i2 = contains_ass_intval(m[i]);
2025 		if(i2 == 2 || (i2 == 1 && m.isFunction())) return 2;
2026 		if(i2 == 1) b  = 1;
2027 	}
2028 	return b;
2029 }
2030 
2031 
mergeInterval(const MathStructure & o,bool set_to_overlap)2032 bool MathStructure::mergeInterval(const MathStructure &o, bool set_to_overlap) {
2033 	if(isNumber() && o.isNumber()) {
2034 		return o_number.mergeInterval(o.number(), set_to_overlap);
2035 	}
2036 	if(equals(o)) return true;
2037 	if(isMultiplication() && SIZE > 1 && CHILD(0).isNumber()) {
2038 		if(o.isMultiplication() && o.size() > 1) {
2039 			if(SIZE == o.size() + (o[0].isNumber() ? 0 : 1)) {
2040 				bool b = true;
2041 				for(size_t i = 1; i < SIZE; i++) {
2042 					if(!CHILD(i).equals(o[0].isNumber() ? o[i] : o[i - 1]) || !CHILD(i).representsNonNegative(true)) {
2043 						b = false;
2044 						break;
2045 					}
2046 				}
2047 				if(b && o[0].isNumber()) {
2048 					if(!CHILD(0).number().mergeInterval(o[0].number(), set_to_overlap)) return false;
2049 				} else if(b) {
2050 					if(!CHILD(0).number().mergeInterval(nr_one, set_to_overlap)) return false;
2051 				}
2052 				CHILD(0).numberUpdated();
2053 				CHILD_UPDATED(0);
2054 				return true;
2055 			}
2056 		} else if(SIZE == 2 && o.equals(CHILD(1)) && o.representsNonNegative(true)) {
2057 			if(!CHILD(0).number().mergeInterval(nr_one, set_to_overlap)) return false;
2058 			CHILD(0).numberUpdated();
2059 			CHILD_UPDATED(0);
2060 			return true;
2061 		}
2062 	} else if(o.isMultiplication() && o.size() == 2 && o[0].isNumber() && equals(o[1]) && representsNonNegative(true)) {
2063 		Number nr(1, 1);
2064 		if(!nr.mergeInterval(o[0].number(), set_to_overlap)) return false;
2065 		transform(STRUCT_MULTIPLICATION);
2066 		PREPEND(nr);
2067 		return true;
2068 	}
2069 	return false;
2070 }
2071 
compare(const MathStructure & o) const2072 ComparisonResult MathStructure::compare(const MathStructure &o) const {
2073 	if(isNumber() && o.isNumber()) {
2074 		return o_number.compare(o.number());
2075 	}
2076 	if(isDateTime() && o.isDateTime()) {
2077 		if(*o_datetime == *o.datetime()) return COMPARISON_RESULT_EQUAL;
2078 		if(*o_datetime > *o.datetime()) return COMPARISON_RESULT_LESS;
2079 		return COMPARISON_RESULT_GREATER;
2080 	}
2081 	if(equals(o)) return COMPARISON_RESULT_EQUAL;
2082 	if(o.isZero()) {
2083 		if(representsPositive(true)) return COMPARISON_RESULT_LESS;
2084 		if(representsNegative(true)) return COMPARISON_RESULT_GREATER;
2085 	}
2086 	if(isMultiplication() && SIZE > 1 && CHILD(0).isNumber()) {
2087 		if(o.isMultiplication() && o.size() > 1) {
2088 			if(SIZE == o.size() + (o[0].isNumber() ? 0 : 1)) {
2089 				bool b = true;
2090 				for(size_t i = 1; i < SIZE; i++) {
2091 					if(!CHILD(i).equals(o[0].isNumber() ? o[i] : o[i - 1]) || !CHILD(i).representsPositive(true)) {
2092 						b = false;
2093 						break;
2094 					}
2095 				}
2096 				if(b && o[0].isNumber()) return CHILD(0).number().compare(o[0].number());
2097 				else if(b) return CHILD(0).number().compare(nr_one);
2098 			}
2099 		} else if(SIZE == 2 && o.equals(CHILD(1)) && o.representsPositive(true)) {
2100 			return CHILD(0).number().compare(nr_one);
2101 		}
2102 	} else if(o.isMultiplication() && o.size() == 2 && o[0].isNumber() && equals(o[1]) && representsPositive(true)) {
2103 		return nr_one.compare(o[0].number());
2104 	}
2105 	if(o.representsReal(true) && representsComplex(true)) return COMPARISON_RESULT_NOT_EQUAL;
2106 	if(representsReal(true) && o.representsComplex(true)) return COMPARISON_RESULT_NOT_EQUAL;
2107 	MathStructure mtest(*this);
2108 	if(!o.isZero()) mtest -= o;
2109 	EvaluationOptions eo = default_evaluation_options;
2110 	eo.approximation = APPROXIMATION_APPROXIMATE;
2111 	eo.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC;
2112 	eo.structuring = STRUCTURING_NONE;
2113 	for(int i = 0; i < 2; i++) {
2114 		int b_ass = (i == 0 ? 2 : contains_ass_intval(mtest));
2115 		if(b_ass == 0) break;
2116 		CALCULATOR->beginTemporaryEnableIntervalArithmetic();
2117 		if(CALCULATOR->usesIntervalArithmetic()) {
2118 			CALCULATOR->beginTemporaryStopMessages();
2119 			replace_interval_unknowns(mtest, i > 0);
2120 			if(b_ass == 2) mtest.calculateFunctions(eo);
2121 			mtest.calculatesub(eo, eo);
2122 			remove_rad_unit(mtest, eo);
2123 			CALCULATOR->endTemporaryStopMessages();
2124 		}
2125 		CALCULATOR->endTemporaryEnableIntervalArithmetic();
2126 		int incomp = 0;
2127 		if(mtest.isAddition()) {
2128 			incomp = compare_check_incompability(&mtest);
2129 		}
2130 		if(incomp > 0) return COMPARISON_RESULT_NOT_EQUAL;
2131 		if(incomp == 0) {
2132 			if(mtest.representsZero(true)) return COMPARISON_RESULT_EQUAL;
2133 			if(mtest.representsPositive(true)) return COMPARISON_RESULT_LESS;
2134 			if(mtest.representsNegative(true)) return COMPARISON_RESULT_GREATER;
2135 			if(mtest.representsNonZero(true)) return COMPARISON_RESULT_NOT_EQUAL;
2136 			if(mtest.representsNonPositive(true)) return COMPARISON_RESULT_EQUAL_OR_GREATER;
2137 			if(mtest.representsNonNegative(true)) return COMPARISON_RESULT_EQUAL_OR_LESS;
2138 		} else if(i == 0) {
2139 			bool a_pos = representsPositive(true);
2140 			bool a_nneg = a_pos || representsNonNegative(true);
2141 			bool a_neg = !a_nneg && representsNegative(true);
2142 			bool a_npos = !a_pos && (a_neg || representsNonPositive(true));
2143 			bool b_pos = o.representsPositive(true);
2144 			bool b_nneg = b_pos || o.representsNonNegative(true);
2145 			bool b_neg = !b_nneg && o.representsNegative(true);
2146 			bool b_npos = !b_pos && (b_neg || o.representsNonPositive(true));
2147 			if(a_pos && b_npos) return COMPARISON_RESULT_NOT_EQUAL;
2148 			if(a_npos && b_pos) return COMPARISON_RESULT_NOT_EQUAL;
2149 			if(a_nneg && b_neg) return COMPARISON_RESULT_NOT_EQUAL;
2150 			if(a_neg && b_nneg) return COMPARISON_RESULT_NOT_EQUAL;
2151 			break;
2152 		}
2153 	}
2154 	return COMPARISON_RESULT_UNKNOWN;
2155 }
2156 
compareApproximately(const MathStructure & o,const EvaluationOptions & eo2) const2157 ComparisonResult MathStructure::compareApproximately(const MathStructure &o, const EvaluationOptions &eo2) const {
2158 	if(isNumber() && o.isNumber()) {
2159 		return o_number.compareApproximately(o.number());
2160 	}
2161 	if(isDateTime() && o.isDateTime()) {
2162 		if(*o_datetime == *o.datetime()) return COMPARISON_RESULT_EQUAL;
2163 		if(*o_datetime < *o.datetime()) return COMPARISON_RESULT_LESS;
2164 		return COMPARISON_RESULT_GREATER;
2165 	}
2166 	if(equals(o)) return COMPARISON_RESULT_EQUAL;
2167 	if(isMultiplication() && SIZE > 1 && CHILD(0).isNumber()) {
2168 		if(o.isMultiplication() && o.size() > 1) {
2169 			if(SIZE == o.size() + (o[0].isNumber() ? 0 : 1)) {
2170 				bool b = true;
2171 				for(size_t i = 1; i < SIZE; i++) {
2172 					if(!CHILD(i).equals(o[0].isNumber() ? o[i] : o[i - 1]) || !CHILD(i).representsPositive(true)) {
2173 						b = false;
2174 						break;
2175 					}
2176 				}
2177 				if(b && o[0].isNumber()) return CHILD(0).number().compareApproximately(o[0].number());
2178 				else if(b) return CHILD(0).number().compareApproximately(nr_one);
2179 			}
2180 		} else if(SIZE == 2 && o.equals(CHILD(1)) && o.representsPositive(true)) {
2181 			return CHILD(0).number().compareApproximately(nr_one);
2182 		}
2183 	} else if(o.isMultiplication() && o.size() == 2 && o[0].isNumber() && equals(o[1]) && representsPositive(true)) {
2184 		return nr_one.compareApproximately(o[0].number());
2185 	}
2186 	if(o.representsZero(true) && representsZero(true)) return COMPARISON_RESULT_EQUAL;
2187 	if(o.representsReal(true) && representsComplex(true)) return COMPARISON_RESULT_NOT_EQUAL;
2188 	if(representsReal(true) && o.representsComplex(true)) return COMPARISON_RESULT_NOT_EQUAL;
2189 	EvaluationOptions eo = eo2;
2190 	eo.expand = true;
2191 	eo.approximation = APPROXIMATION_APPROXIMATE;
2192 	eo.structuring = STRUCTURING_NONE;
2193 	for(int i = 0; i < 2; i++) {
2194 		int b_ass1 = (i == 0 ? 2 : contains_ass_intval(*this));
2195 		int b_ass2 = (i == 0 ? 2 : contains_ass_intval(o));
2196 		if(b_ass1 == 0 && b_ass2 == 0) break;
2197 		CALCULATOR->beginTemporaryStopMessages();
2198 		MathStructure mtest(*this), mtest2(o);
2199 		if(b_ass1 > 0) replace_interval_unknowns(mtest, i > 0);
2200 		if(b_ass2 > 0) replace_interval_unknowns(mtest2, i > 0);
2201 		if(b_ass1 == 2) mtest.calculateFunctions(eo);
2202 		if(b_ass2 == 2) mtest2.calculateFunctions(eo);
2203 		if(b_ass1 > 0) mtest.calculatesub(eo, eo);
2204 		if(b_ass2 > 0) mtest2.calculatesub(eo, eo);
2205 		remove_rad_unit(mtest, eo);
2206 		remove_rad_unit(mtest2, eo);
2207 		CALCULATOR->endTemporaryStopMessages();
2208 		if(mtest.equals(mtest2)) return COMPARISON_RESULT_EQUAL;
2209 		if(mtest.representsZero(true) && mtest2.representsZero(true)) return COMPARISON_RESULT_EQUAL;
2210 		if(mtest.isNumber() && mtest2.isNumber()) {
2211 			if(mtest2.isApproximate() && o.isAddition() && o.size() > 1 && mtest.isZero() && !mtest2.isZero()) {
2212 				CALCULATOR->beginTemporaryStopMessages();
2213 				mtest = *this;
2214 				mtest.subtract(o[0]);
2215 				mtest2 = o;
2216 				mtest2.delChild(1, true);
2217 				replace_interval_unknowns(mtest, i > 0);
2218 				replace_interval_unknowns(mtest2, i > 0);
2219 				mtest.calculateFunctions(eo);
2220 				mtest2.calculateFunctions(eo);
2221 				mtest.calculatesub(eo, eo);
2222 				mtest2.calculatesub(eo, eo);
2223 				remove_rad_unit(mtest, eo);
2224 				remove_rad_unit(mtest2, eo);
2225 				CALCULATOR->endTemporaryStopMessages();
2226 				if(mtest.isNumber() && mtest2.isNumber()) return mtest.number().compareApproximately(mtest2.number());
2227 			} else if(mtest.isApproximate() && isAddition() && SIZE > 1 && mtest2.isZero() && !mtest.isZero()) {
2228 				CALCULATOR->beginTemporaryStopMessages();
2229 				mtest2 = o;
2230 				mtest2.subtract(CHILD(0));
2231 				mtest = *this;
2232 				mtest.delChild(1, true);
2233 				replace_interval_unknowns(mtest, i > 0);
2234 				replace_interval_unknowns(mtest2, i > 0);
2235 				mtest.calculateFunctions(eo);
2236 				mtest2.calculateFunctions(eo);
2237 				mtest.calculatesub(eo, eo);
2238 				mtest2.calculatesub(eo, eo);
2239 				remove_rad_unit(mtest, eo);
2240 				remove_rad_unit(mtest2, eo);
2241 				CALCULATOR->endTemporaryStopMessages();
2242 				if(mtest.isNumber() && mtest2.isNumber()) return mtest.number().compareApproximately(mtest2.number());
2243 			} else {
2244 				return mtest.number().compareApproximately(mtest2.number());
2245 			}
2246 		}
2247 		if(mtest2.isZero() && mtest.isMultiplication() && mtest.size() > 0 && mtest[0].isNumber()) {
2248 			bool b = true;
2249 			for(size_t i = 1; i < SIZE; i++) {
2250 				if(!CHILD(i).representsNonZero(true)) {
2251 					b = false;
2252 					break;
2253 				}
2254 			}
2255 			if(b) return CHILD(0).number().compareApproximately(o.number());
2256 		}
2257 		if(!mtest2.isZero()) {
2258 			CALCULATOR->beginTemporaryStopMessages();
2259 			mtest.calculateSubtract(mtest2, eo);
2260 			CALCULATOR->endTemporaryStopMessages();
2261 		}
2262 		if(mtest.representsZero(true)) return COMPARISON_RESULT_EQUAL;
2263 		int incomp = 0;
2264 		if(mtest.isAddition()) {
2265 			incomp = compare_check_incompability(&mtest);
2266 		}
2267 		if(incomp > 0) return COMPARISON_RESULT_NOT_EQUAL;
2268 		if(incomp == 0) {
2269 			if(mtest.isZero()) return COMPARISON_RESULT_EQUAL;
2270 			if(mtest.representsPositive(true)) return COMPARISON_RESULT_LESS;
2271 			if(mtest.representsNegative(true)) return COMPARISON_RESULT_GREATER;
2272 			if(mtest.representsNonZero(true)) return COMPARISON_RESULT_NOT_EQUAL;
2273 			if(mtest.representsNonPositive(true)) return COMPARISON_RESULT_EQUAL_OR_GREATER;
2274 			if(mtest.representsNonNegative(true)) return COMPARISON_RESULT_EQUAL_OR_LESS;
2275 		} else if(i == 0) {
2276 			bool a_pos = representsPositive(true);
2277 			bool a_nneg = a_pos || representsNonNegative(true);
2278 			bool a_neg = !a_nneg && representsNegative(true);
2279 			bool a_npos = !a_pos && (a_neg || representsNonPositive(true));
2280 			bool b_pos = o.representsPositive(true);
2281 			bool b_nneg = b_pos || o.representsNonNegative(true);
2282 			bool b_neg = !b_nneg && o.representsNegative(true);
2283 			bool b_npos = !b_pos && (b_neg || o.representsNonPositive(true));
2284 			if(a_pos && b_npos) return COMPARISON_RESULT_NOT_EQUAL;
2285 			if(a_npos && b_pos) return COMPARISON_RESULT_NOT_EQUAL;
2286 			if(a_nneg && b_neg) return COMPARISON_RESULT_NOT_EQUAL;
2287 			if(a_neg && b_nneg) return COMPARISON_RESULT_NOT_EQUAL;
2288 			break;
2289 		}
2290 	}
2291 	return COMPARISON_RESULT_UNKNOWN;
2292 }
2293 
containsOpaqueContents() const2294 bool MathStructure::containsOpaqueContents() const {
2295 	if(isFunction()) return true;
2296 	if(isUnit() && o_unit->subtype() != SUBTYPE_BASE_UNIT) return true;
2297 	if(isVariable() && o_variable->isKnown()) return true;
2298 	for(size_t i = 0; i < SIZE; i++) {
2299 		if(CHILD(i).containsOpaqueContents()) return true;
2300 	}
2301 	return false;
2302 }
containsAdditionPower() const2303 bool MathStructure::containsAdditionPower() const {
2304 	if(m_type == STRUCT_POWER && CHILD(0).isAddition()) return true;
2305 	for(size_t i = 0; i < SIZE; i++) {
2306 		if(CHILD(i).containsAdditionPower()) return true;
2307 	}
2308 	return false;
2309 }
2310 
countTotalChildren(bool count_function_as_one) const2311 size_t MathStructure::countTotalChildren(bool count_function_as_one) const {
2312 	if((m_type == STRUCT_FUNCTION && count_function_as_one) || SIZE == 0) return 1;
2313 	size_t count = 0;
2314 	for(size_t i = 0; i < SIZE; i++) {
2315 		count += CHILD(i).countTotalChildren() + 1;
2316 	}
2317 	return count;
2318 }
2319 
swapChildren(size_t index1,size_t index2)2320 void MathStructure::swapChildren(size_t index1, size_t index2) {
2321 	if(index1 > 0 && index2 > 0 && index1 <= SIZE && index2 <= SIZE) {
2322 		SWAP_CHILDREN(index1 - 1, index2 - 1)
2323 	}
2324 }
childToFront(size_t index)2325 void MathStructure::childToFront(size_t index) {
2326 	if(index > 0 && index <= SIZE) {
2327 		CHILD_TO_FRONT(index - 1)
2328 	}
2329 }
addChild(const MathStructure & o)2330 void MathStructure::addChild(const MathStructure &o) {
2331 	APPEND(o);
2332 }
addChild_nocopy(MathStructure * o)2333 void MathStructure::addChild_nocopy(MathStructure *o) {
2334 	APPEND_POINTER(o);
2335 }
delChild(size_t index,bool check_size)2336 void MathStructure::delChild(size_t index, bool check_size) {
2337 	if(index > 0 && index <= SIZE) {
2338 		ERASE(index - 1);
2339 		if(check_size) {
2340 			if(SIZE == 1) setToChild(1, true);
2341 			else if(SIZE == 0) clear(true);
2342 		}
2343 	}
2344 }
insertChild(const MathStructure & o,size_t index)2345 void MathStructure::insertChild(const MathStructure &o, size_t index) {
2346 	if(index > 0 && index <= v_subs.size()) {
2347 		v_order.insert(v_order.begin() + (index - 1), v_subs.size());
2348 		v_subs.push_back(new MathStructure(o));
2349 		CHILD_UPDATED(index - 1);
2350 	} else {
2351 		addChild(o);
2352 	}
2353 }
insertChild_nocopy(MathStructure * o,size_t index)2354 void MathStructure::insertChild_nocopy(MathStructure *o, size_t index) {
2355 	if(index > 0 && index <= v_subs.size()) {
2356 		v_order.insert(v_order.begin() + (index - 1), v_subs.size());
2357 		v_subs.push_back(o);
2358 		CHILD_UPDATED(index - 1);
2359 	} else {
2360 		addChild_nocopy(o);
2361 	}
2362 }
setChild(const MathStructure & o,size_t index,bool merge_precision)2363 void MathStructure::setChild(const MathStructure &o, size_t index, bool merge_precision) {
2364 	if(index > 0 && index <= SIZE) {
2365 		CHILD(index - 1).set(o, merge_precision);
2366 		CHILD_UPDATED(index - 1);
2367 	}
2368 }
setChild_nocopy(MathStructure * o,size_t index,bool merge_precision)2369 void MathStructure::setChild_nocopy(MathStructure *o, size_t index, bool merge_precision) {
2370 	if(index > 0 && index <= SIZE) {
2371 		MathStructure *o_prev = v_subs[v_order[index - 1]];
2372 		if(merge_precision) {
2373 			if(!o->isApproximate() && o_prev->isApproximate()) o->setApproximate(true);
2374 			if(o_prev->precision() >= 0 && (o->precision() < 0 || o_prev->precision() < o->precision())) o->setPrecision(o_prev->precision());
2375 		}
2376 		o_prev->unref();
2377 		v_subs[v_order[index - 1]] = o;
2378 		CHILD_UPDATED(index - 1);
2379 	}
2380 }
getChild(size_t index) const2381 const MathStructure *MathStructure::getChild(size_t index) const {
2382 	if(index > 0 && index <= v_order.size()) {
2383 		return &CHILD(index - 1);
2384 	}
2385 	return NULL;
2386 }
getChild(size_t index)2387 MathStructure *MathStructure::getChild(size_t index) {
2388 	if(index > 0 && index <= v_order.size()) {
2389 		return &CHILD(index - 1);
2390 	}
2391 	return NULL;
2392 }
countChildren() const2393 size_t MathStructure::countChildren() const {
2394 	return SIZE;
2395 }
size() const2396 size_t MathStructure::size() const {
2397 	return SIZE;
2398 }
base() const2399 const MathStructure *MathStructure::base() const {
2400 	if(m_type == STRUCT_POWER && SIZE >= 1) {
2401 		return &CHILD(0);
2402 	}
2403 	return NULL;
2404 }
exponent() const2405 const MathStructure *MathStructure::exponent() const {
2406 	if(m_type == STRUCT_POWER && SIZE >= 2) {
2407 		return &CHILD(1);
2408 	}
2409 	return NULL;
2410 }
base()2411 MathStructure *MathStructure::base() {
2412 	if(m_type == STRUCT_POWER && SIZE >= 1) {
2413 		return &CHILD(0);
2414 	}
2415 	return NULL;
2416 }
exponent()2417 MathStructure *MathStructure::exponent() {
2418 	if(m_type == STRUCT_POWER && SIZE >= 2) {
2419 		return &CHILD(1);
2420 	}
2421 	return NULL;
2422 }
2423 
type() const2424 StructureType MathStructure::type() const {
2425 	return m_type;
2426 }
2427 
contains_angle_unit(const MathStructure & m,const ParseOptions & po)2428 bool contains_angle_unit(const MathStructure &m, const ParseOptions &po) {
2429 	if(m.isUnit() && m.unit()->baseUnit() == CALCULATOR->getRadUnit()->baseUnit()) return true;
2430 	if(m.isVariable() && m.variable()->isKnown()) return contains_angle_unit(((KnownVariable*) m.variable())->get(), po);
2431 	if(m.isFunction()) return po.angle_unit == ANGLE_UNIT_NONE && (m.function()->id() == FUNCTION_ID_ASIN || m.function()->id() == FUNCTION_ID_ACOS || m.function()->id() == FUNCTION_ID_ATAN);
2432 	for(size_t i = 0; i < m.size(); i++) {
2433 		if(contains_angle_unit(m[i], po)) return true;
2434 	}
2435 	return false;
2436 }
2437 
contains(const MathStructure & mstruct,bool structural_only,bool check_variables,bool check_functions,bool loose_equals) const2438 int MathStructure::contains(const MathStructure &mstruct, bool structural_only, bool check_variables, bool check_functions, bool loose_equals) const {
2439 	if(mstruct.isUnit() && mstruct.prefix() == NULL && m_type == STRUCT_UNIT) return mstruct.unit() == o_unit;
2440 	if(equals(mstruct, loose_equals, loose_equals)) return 1;
2441 	if(structural_only) {
2442 		for(size_t i = 0; i < SIZE; i++) {
2443 			if(CHILD(i).contains(mstruct, structural_only, check_variables, check_functions, loose_equals)) return 1;
2444 		}
2445 		if(m_type == STRUCT_VARIABLE && check_variables && o_variable->isKnown()) {
2446 			return ((KnownVariable*) o_variable)->get().contains(mstruct, structural_only, check_variables, check_functions, loose_equals);
2447 		} else if(m_type == STRUCT_FUNCTION && check_functions) {
2448 			if(function_value) {
2449 				return function_value->contains(mstruct, structural_only, check_variables, check_functions, loose_equals);
2450 			}
2451 		}
2452 	} else {
2453 		int ret = 0;
2454 		if(m_type != STRUCT_FUNCTION) {
2455 			for(size_t i = 0; i < SIZE; i++) {
2456 				int retval = CHILD(i).contains(mstruct, structural_only, check_variables, check_functions, loose_equals);
2457 				if(retval == 1) return 1;
2458 				else if(retval < 0) ret = retval;
2459 			}
2460 		}
2461 		if(m_type == STRUCT_VARIABLE && check_variables && o_variable->isKnown()) {
2462 			return ((KnownVariable*) o_variable)->get().contains(mstruct, structural_only, check_variables, check_functions, loose_equals);
2463 		} else if(m_type == STRUCT_FUNCTION && check_functions) {
2464 			if(function_value) {
2465 				return function_value->contains(mstruct, structural_only, check_variables, check_functions, loose_equals);
2466 			}
2467 			return -1;
2468 		} else if(isAborted()) {
2469 			return -1;
2470 		}
2471 		return ret;
2472 	}
2473 	return 0;
2474 }
countOccurrences(const MathStructure & mstruct) const2475 size_t MathStructure::countOccurrences(const MathStructure &mstruct) const {
2476 	if(mstruct.isUnit() && mstruct.prefix() == NULL && m_type == STRUCT_UNIT && mstruct.unit() == o_unit) return 1;
2477 	if(equals(mstruct, true, true)) return 1;
2478 	size_t i_occ = 0;
2479 	for(size_t i = 0; i < SIZE; i++) {
2480 		i_occ += CHILD(i).countOccurrences(mstruct);
2481 	}
2482 	return i_occ;
2483 }
containsFunction(MathFunction * f,bool structural_only,bool check_variables,bool check_functions) const2484 int MathStructure::containsFunction(MathFunction *f, bool structural_only, bool check_variables, bool check_functions) const {
2485 	if(m_type == STRUCT_FUNCTION && o_function == f) return 1;
2486 	if(structural_only) {
2487 		for(size_t i = 0; i < SIZE; i++) {
2488 			if(CHILD(i).containsFunction(f, structural_only, check_variables, check_functions)) return 1;
2489 		}
2490 		if(m_type == STRUCT_VARIABLE && check_variables && o_variable->isKnown()) {
2491 			return ((KnownVariable*) o_variable)->get().containsFunction(f, structural_only, check_variables, check_functions);
2492 		} else if(m_type == STRUCT_FUNCTION && check_functions) {
2493 			if(function_value) {
2494 				return function_value->containsFunction(f, structural_only, check_variables, check_functions);
2495 			}
2496 		}
2497 	} else {
2498 		int ret = 0;
2499 		if(m_type != STRUCT_FUNCTION) {
2500 			for(size_t i = 0; i < SIZE; i++) {
2501 				int retval = CHILD(i).containsFunction(f, structural_only, check_variables, check_functions);
2502 				if(retval == 1) return 1;
2503 				else if(retval < 0) ret = retval;
2504 			}
2505 		}
2506 		if(m_type == STRUCT_VARIABLE && check_variables && o_variable->isKnown()) {
2507 			return ((KnownVariable*) o_variable)->get().containsFunction(f, structural_only, check_variables, check_functions);
2508 		} else if(m_type == STRUCT_FUNCTION && check_functions) {
2509 			if(function_value) {
2510 				return function_value->containsFunction(f, structural_only, check_variables, check_functions);
2511 			}
2512 			return -1;
2513 		} else if(isAborted()) {
2514 			return -1;
2515 		}
2516 		return ret;
2517 	}
2518 	return 0;
2519 }
containsFunctionId(int id,bool structural_only,bool check_variables,bool check_functions) const2520 int MathStructure::containsFunctionId(int id, bool structural_only, bool check_variables, bool check_functions) const {
2521 	if(m_type == STRUCT_FUNCTION && o_function->id() == id) return 1;
2522 	if(structural_only) {
2523 		for(size_t i = 0; i < SIZE; i++) {
2524 			if(CHILD(i).containsFunctionId(id, structural_only, check_variables, check_functions)) return 1;
2525 		}
2526 		if(m_type == STRUCT_VARIABLE && check_variables && o_variable->isKnown()) {
2527 			return ((KnownVariable*) o_variable)->get().containsFunctionId(id, structural_only, check_variables, check_functions);
2528 		} else if(m_type == STRUCT_FUNCTION && check_functions) {
2529 			if(function_value) {
2530 				return function_value->containsFunctionId(id, structural_only, check_variables, check_functions);
2531 			}
2532 		}
2533 	} else {
2534 		int ret = 0;
2535 		if(m_type != STRUCT_FUNCTION) {
2536 			for(size_t i = 0; i < SIZE; i++) {
2537 				int retval = CHILD(i).containsFunctionId(id, structural_only, check_variables, check_functions);
2538 				if(retval == 1) return 1;
2539 				else if(retval < 0) ret = retval;
2540 			}
2541 		}
2542 		if(m_type == STRUCT_VARIABLE && check_variables && o_variable->isKnown()) {
2543 			return ((KnownVariable*) o_variable)->get().containsFunctionId(id, structural_only, check_variables, check_functions);
2544 		} else if(m_type == STRUCT_FUNCTION && check_functions) {
2545 			if(function_value) {
2546 				return function_value->containsFunctionId(id, structural_only, check_variables, check_functions);
2547 			}
2548 			return -1;
2549 		} else if(isAborted()) {
2550 			return -1;
2551 		}
2552 		return ret;
2553 	}
2554 	return 0;
2555 }
contains_interval_var(const MathStructure & m,bool structural_only,bool check_variables,bool check_functions,int ignore_high_precision_interval,bool include_interval_function)2556 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) {
2557 	if(m.type() == STRUCT_NUMBER) {
2558 		if(m.number().isInterval(false)) {
2559 			if(ignore_high_precision_interval != 0) {
2560 				if(m.number().precision(true) > (ignore_high_precision_interval < 0 ? (ignore_high_precision_interval == -1 ? PRECISION + 29 : PRECISION - ignore_high_precision_interval) : PRECISION + (10 * ignore_high_precision_interval))) return 0;
2561 			}
2562 			return 1;
2563 		} else if(CALCULATOR->usesIntervalArithmetic() && m.number().precision() >= 0) {
2564 			if(ignore_high_precision_interval != 0) {
2565 				if(m.number().precision() > (ignore_high_precision_interval < 0 ? (ignore_high_precision_interval == -1 ? PRECISION + 29 : PRECISION - ignore_high_precision_interval) : PRECISION + (10 * ignore_high_precision_interval))) return 0;
2566 			}
2567 			return 1;
2568 		}
2569 	}
2570 	if(m.type() == STRUCT_FUNCTION && (m.function()->id() == FUNCTION_ID_INTERVAL || m.function()->id() == FUNCTION_ID_UNCERTAINTY)) return include_interval_function;
2571 	if(structural_only) {
2572 		for(size_t i = 0; i < m.size(); i++) {
2573 			if(contains_interval_var(m[i], structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function)) return 1;
2574 		}
2575 		if(m.type() == STRUCT_VARIABLE && check_variables && m.variable()->isKnown()) {
2576 			return contains_interval_var(((KnownVariable*) m.variable())->get(), structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function);
2577 		} else if(m.type() == STRUCT_FUNCTION && check_functions) {
2578 			if(m.functionValue()) {
2579 				return contains_interval_var(*m.functionValue(), structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function);
2580 			}
2581 		}
2582 	} else {
2583 		int ret = 0;
2584 		if(m.type() != STRUCT_FUNCTION) {
2585 			for(size_t i = 0; i < m.size(); i++) {
2586 				int retval = contains_interval_var(m[i], structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function);
2587 				if(retval == 1) return 1;
2588 				else if(retval < 0) ret = retval;
2589 			}
2590 		}
2591 		if(m.type() == STRUCT_VARIABLE && check_variables && m.variable()->isKnown()) {
2592 			return contains_interval_var(((KnownVariable*) m.variable())->get(), structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function);
2593 		} else if(m.type() == STRUCT_FUNCTION && check_functions) {
2594 			if(m.functionValue()) {
2595 				return contains_interval_var(*m.functionValue(), structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function);
2596 			}
2597 			return -1;
2598 		} else if(m.isAborted()) {
2599 			return -1;
2600 		}
2601 		return ret;
2602 	}
2603 	return 0;
2604 }
containsInterval(bool structural_only,bool check_variables,bool check_functions,int ignore_high_precision_interval,bool include_interval_function) const2605 int MathStructure::containsInterval(bool structural_only, bool check_variables, bool check_functions, int ignore_high_precision_interval, bool include_interval_function) const {
2606 	if(m_type == STRUCT_NUMBER && o_number.isInterval(false)) {
2607 		if(ignore_high_precision_interval != 0) {
2608 			if(o_number.precision(true) > (ignore_high_precision_interval < 0 ? (ignore_high_precision_interval == -1 ? PRECISION + 29 : PRECISION - ignore_high_precision_interval) : PRECISION + (10 * ignore_high_precision_interval))) return 0;
2609 		}
2610 		return 1;
2611 	}
2612 	if(m_type == STRUCT_FUNCTION && (o_function->id() == FUNCTION_ID_INTERVAL || o_function->id() == FUNCTION_ID_UNCERTAINTY)) return include_interval_function;
2613 	if(structural_only) {
2614 		for(size_t i = 0; i < SIZE; i++) {
2615 			if(CHILD(i).containsInterval(structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function)) return 1;
2616 		}
2617 		if(m_type == STRUCT_VARIABLE && check_variables && o_variable->isKnown()) {
2618 			if(ignore_high_precision_interval == -1 && o_variable->isBuiltin()) {
2619 				return 0;
2620 			}
2621 			return contains_interval_var(((KnownVariable*) o_variable)->get(), structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function);
2622 		} else if(m_type == STRUCT_FUNCTION && check_functions) {
2623 			if(function_value) {
2624 				return function_value->containsInterval(structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function);
2625 			}
2626 		}
2627 	} else {
2628 		int ret = 0;
2629 		if(m_type != STRUCT_FUNCTION) {
2630 			for(size_t i = 0; i < SIZE; i++) {
2631 				int retval = CHILD(i).containsInterval(structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function);
2632 				if(retval == 1) return 1;
2633 				else if(retval < 0) ret = retval;
2634 			}
2635 		}
2636 		if(m_type == STRUCT_VARIABLE && check_variables && o_variable->isKnown()) {
2637 			if(ignore_high_precision_interval == -1 && o_variable->isBuiltin()) {
2638 				return 0;
2639 			}
2640 			return contains_interval_var(((KnownVariable*) o_variable)->get(), structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function);
2641 		} else if(m_type == STRUCT_FUNCTION && check_functions) {
2642 			if(function_value) {
2643 				return function_value->containsInterval(structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function);
2644 			}
2645 			return -1;
2646 		} else if(isAborted()) {
2647 			return -1;
2648 		}
2649 		return ret;
2650 	}
2651 	return 0;
2652 }
containsInfinity(bool structural_only,bool check_variables,bool check_functions) const2653 int MathStructure::containsInfinity(bool structural_only, bool check_variables, bool check_functions) const {
2654 	if(m_type == STRUCT_NUMBER && o_number.includesInfinity(false)) {
2655 		return 1;
2656 	}
2657 	if(structural_only) {
2658 		for(size_t i = 0; i < SIZE; i++) {
2659 			if(CHILD(i).containsInfinity(structural_only, check_variables, check_functions)) return 1;
2660 		}
2661 		if(m_type == STRUCT_VARIABLE && check_variables && o_variable->isKnown()) {
2662 			return ((KnownVariable*) o_variable)->get().containsInfinity(structural_only, check_variables, check_functions);
2663 		} else if(m_type == STRUCT_FUNCTION && check_functions) {
2664 			if(function_value) {
2665 				return function_value->containsInfinity(structural_only, check_variables, check_functions);
2666 			}
2667 		}
2668 	} else {
2669 		int ret = 0;
2670 		if(m_type != STRUCT_FUNCTION) {
2671 			for(size_t i = 0; i < SIZE; i++) {
2672 				int retval = CHILD(i).containsInfinity(structural_only, check_variables, check_functions);
2673 				if(retval == 1) return 1;
2674 				else if(retval < 0) ret = retval;
2675 			}
2676 		}
2677 		if(m_type == STRUCT_VARIABLE && check_variables && o_variable->isKnown()) {
2678 			return ((KnownVariable*) o_variable)->get().containsInfinity(structural_only, check_variables, check_functions);
2679 		} else if(m_type == STRUCT_FUNCTION && check_functions) {
2680 			if(function_value) {
2681 				return function_value->containsInfinity(structural_only, check_variables, check_functions);
2682 			}
2683 			return -1;
2684 		} else if(isAborted()) {
2685 			return -1;
2686 		}
2687 		return ret;
2688 	}
2689 	return 0;
2690 }
2691 
containsRepresentativeOf(const MathStructure & mstruct,bool check_variables,bool check_functions) const2692 int MathStructure::containsRepresentativeOf(const MathStructure &mstruct, bool check_variables, bool check_functions) const {
2693 	if(equals(mstruct)) return 1;
2694 	int ret = 0;
2695 	if(m_type != STRUCT_FUNCTION) {
2696 		for(size_t i = 0; i < SIZE; i++) {
2697 			int retval = CHILD(i).containsRepresentativeOf(mstruct, check_variables, check_functions);
2698 			if(retval == 1) return 1;
2699 			else if(retval < 0) ret = retval;
2700 		}
2701 	}
2702 	if(m_type == STRUCT_VARIABLE && check_variables) {
2703 		if(o_variable->isKnown()) return ((KnownVariable*) o_variable)->get().containsRepresentativeOf(mstruct, check_variables, check_functions);
2704 		else return ((UnknownVariable*) o_variable)->interval().containsRepresentativeOf(mstruct, check_variables, check_functions);
2705 	} else if(m_type == STRUCT_FUNCTION && check_functions) {
2706 		if(function_value) {
2707 			return function_value->containsRepresentativeOf(mstruct, check_variables, check_functions);
2708 		}
2709 		if(!mstruct.isNumber() && (o_function->isBuiltin() || representsNumber())) {
2710 			for(size_t i = 0; i < SIZE; i++) {
2711 				int retval = CHILD(i).containsRepresentativeOf(mstruct, check_variables, check_functions);
2712 				if(retval != 0) return -1;
2713 			}
2714 			return 0;
2715 		}
2716 		return -1;
2717 	} else if(isAborted()) {
2718 		return -1;
2719 	}
2720 	return ret;
2721 }
2722 
containsType(StructureType mtype,bool structural_only,bool check_variables,bool check_functions) const2723 int MathStructure::containsType(StructureType mtype, bool structural_only, bool check_variables, bool check_functions) const {
2724 	if(m_type == mtype) return 1;
2725 	if(structural_only) {
2726 		for(size_t i = 0; i < SIZE; i++) {
2727 			if(CHILD(i).containsType(mtype, true, check_variables, check_functions)) return 1;
2728 		}
2729 		if(check_variables && m_type == STRUCT_VARIABLE && o_variable->isKnown()) {
2730 			return ((KnownVariable*) o_variable)->get().containsType(mtype, false, check_variables, check_functions);
2731 		} else if(check_functions && m_type == STRUCT_FUNCTION) {
2732 			if(function_value) {
2733 				return function_value->containsType(mtype, false, check_variables, check_functions);
2734 			}
2735 		}
2736 		return 0;
2737 	} else {
2738 		int ret = 0;
2739 		if(m_type != STRUCT_FUNCTION) {
2740 			for(size_t i = 0; i < SIZE; i++) {
2741 				int retval = CHILD(i).containsType(mtype, false, check_variables, check_functions);
2742 				if(retval == 1) return 1;
2743 				else if(retval < 0) ret = retval;
2744 			}
2745 		}
2746 		if(check_variables && m_type == STRUCT_VARIABLE) {
2747 			if(o_variable->isKnown()) return ((KnownVariable*) o_variable)->get().containsType(mtype, false, check_variables, check_functions);
2748 			else if(!((UnknownVariable*) o_variable)->interval().isUndefined()) return ((UnknownVariable*) o_variable)->interval().containsType(mtype, false, check_variables, check_functions);
2749 			else if(mtype == STRUCT_UNIT) return -1;
2750 		} else if(check_functions && m_type == STRUCT_FUNCTION) {
2751 			if(function_value) {
2752 				return function_value->containsType(mtype, false, check_variables, check_functions);
2753 			}
2754 			if(mtype == STRUCT_UNIT) {
2755 				if(o_function->id() == FUNCTION_ID_STRIP_UNITS) return 0;
2756 				if(o_function->subtype() == SUBTYPE_USER_FUNCTION || o_function->id() == FUNCTION_ID_REGISTER || o_function->id() == FUNCTION_ID_STACK || o_function->id() == FUNCTION_ID_LOAD) return -1;
2757 				// (eo.parse_options.angle_unit == ANGLE_UNIT_NONE && (o_function->id() == FUNCTION_ID_ASIN || o_function->id() == FUNCTION_ID_ACOS || o_function->id() == FUNCTION_ID_ATAN || o_function->id() == FUNCTION_ID_RADIANS_TO_DEFAULT_ANGLE_UNIT))
2758 				if(o_function->id() == FUNCTION_ID_LOG || o_function->id() == FUNCTION_ID_LOGN || o_function->id() == FUNCTION_ID_ARG || o_function->id() == FUNCTION_ID_GAMMA || o_function->id() == FUNCTION_ID_BETA || o_function->id() == FUNCTION_ID_FACTORIAL || o_function->id() == FUNCTION_ID_BESSELJ || o_function->id() == FUNCTION_ID_BESSELY || o_function->id() == FUNCTION_ID_ERF || o_function->id() == FUNCTION_ID_ERFI || o_function->id() == FUNCTION_ID_ERFC || o_function->id() == FUNCTION_ID_LOGINT || o_function->id() == FUNCTION_ID_POLYLOG || o_function->id() == FUNCTION_ID_EXPINT || o_function->id() == FUNCTION_ID_SININT || o_function->id() == FUNCTION_ID_COSINT || o_function->id() == FUNCTION_ID_SINHINT || o_function->id() == FUNCTION_ID_COSHINT || o_function->id() == FUNCTION_ID_FRESNEL_C || o_function->id() == FUNCTION_ID_FRESNEL_S || o_function->id() == FUNCTION_ID_SIGNUM || o_function->id() == FUNCTION_ID_HEAVISIDE || o_function->id() == FUNCTION_ID_LAMBERT_W || o_function->id() == FUNCTION_ID_SINC || o_function->id() == FUNCTION_ID_SIN || o_function->id() == FUNCTION_ID_COS || o_function->id() == FUNCTION_ID_TAN || o_function->id() == FUNCTION_ID_SINH || o_function->id() == FUNCTION_ID_COSH || o_function->id() == FUNCTION_ID_TANH || o_function->id() == FUNCTION_ID_ASINH || o_function->id() == FUNCTION_ID_ACOSH || o_function->id() == FUNCTION_ID_ATANH || o_function->id() == FUNCTION_ID_ASIN || o_function->id() == FUNCTION_ID_ACOS || o_function->id() == FUNCTION_ID_ATAN) return 0;
2759 				int ret = 0;
2760 				for(size_t i = 0; i < SIZE; i++) {
2761 					int ret_i = CHILD(i).containsType(mtype, false, check_variables, check_functions);
2762 					if(ret_i > 0) return ret_i;
2763 					else if(ret_i < 0) ret = ret_i;
2764 				}
2765 				return ret;
2766 			}
2767 			return -1;
2768 		} else if(isAborted()) {
2769 			return -1;
2770 		}
2771 		return ret;
2772 	}
2773 }
containsRepresentativeOfType(StructureType mtype,bool check_variables,bool check_functions) const2774 int MathStructure::containsRepresentativeOfType(StructureType mtype, bool check_variables, bool check_functions) const {
2775 	if(m_type == mtype) return 1;
2776 	int ret = 0;
2777 	if(m_type != STRUCT_FUNCTION) {
2778 		for(size_t i = 0; i < SIZE; i++) {
2779 			int retval = CHILD(i).containsRepresentativeOfType(mtype, check_variables, check_functions);
2780 			if(retval == 1) return 1;
2781 			else if(retval < 0) ret = retval;
2782 		}
2783 	}
2784 	if(check_variables && m_type == STRUCT_VARIABLE && o_variable->isKnown()) {
2785 		return ((KnownVariable*) o_variable)->get().containsRepresentativeOfType(mtype, check_variables, check_functions);
2786 	} else if(check_functions && m_type == STRUCT_FUNCTION) {
2787 		if(function_value) {
2788 			return function_value->containsRepresentativeOfType(mtype, check_variables, check_functions);
2789 		}
2790 	}
2791 	if(m_type == STRUCT_SYMBOLIC || m_type == STRUCT_VARIABLE || m_type == STRUCT_FUNCTION || m_type == STRUCT_ABORTED) {
2792 		if(representsNumber(false)) {
2793 			if(mtype == STRUCT_UNIT) return -1;
2794 			return mtype == STRUCT_NUMBER;
2795 		} else {
2796 			return -1;
2797 		}
2798 	}
2799 	return ret;
2800 }
containsUnknowns() const2801 bool MathStructure::containsUnknowns() const {
2802 	if(isUnknown()) return true;
2803 	for(size_t i = 0; i < SIZE; i++) {
2804 		if(CHILD(i).containsUnknowns()) return true;
2805 	}
2806 	return false;
2807 }
containsDivision() const2808 bool MathStructure::containsDivision() const {
2809 	if(m_type == STRUCT_DIVISION || m_type == STRUCT_INVERSE || (m_type == STRUCT_POWER && CHILD(1).hasNegativeSign())) return true;
2810 	for(size_t i = 0; i < SIZE; i++) {
2811 		if(CHILD(i).containsDivision()) return true;
2812 	}
2813 	return false;
2814 }
countFunctions(bool count_subfunctions) const2815 size_t MathStructure::countFunctions(bool count_subfunctions) const {
2816 	size_t c = 0;
2817 	if(isFunction()) {
2818 		if(!count_subfunctions) return 1;
2819 		c = 1;
2820 	}
2821 	for(size_t i = 0; i < SIZE; i++) {
2822 		c += CHILD(i).countFunctions();
2823 	}
2824 	return c;
2825 }
findAllUnknowns(MathStructure & unknowns_vector)2826 void MathStructure::findAllUnknowns(MathStructure &unknowns_vector) {
2827 	if(!unknowns_vector.isVector()) unknowns_vector.clearVector();
2828 	switch(m_type) {
2829 		case STRUCT_VARIABLE: {
2830 			if(o_variable->isKnown()) {
2831 				break;
2832 			}
2833 		}
2834 		case STRUCT_SYMBOLIC: {
2835 			bool b = false;
2836 			for(size_t i = 0; i < unknowns_vector.size(); i++) {
2837 				if(equals(unknowns_vector[i])) {
2838 					b = true;
2839 					break;
2840 				}
2841 			}
2842 			if(!b) unknowns_vector.addChild(*this);
2843 			break;
2844 		}
2845 		default: {
2846 			for(size_t i = 0; i < SIZE; i++) {
2847 				CHILD(i).findAllUnknowns(unknowns_vector);
2848 			}
2849 		}
2850 	}
2851 }
replace(const MathStructure & mfrom,const MathStructure & mto,bool once_only,bool exclude_function_arguments)2852 bool MathStructure::replace(const MathStructure &mfrom, const MathStructure &mto, bool once_only, bool exclude_function_arguments) {
2853 	if(b_protected) b_protected = false;
2854 	if(equals(mfrom, true, true)) {
2855 		set(mto);
2856 		return true;
2857 	}
2858 	if(mfrom.size() > 0 && mfrom.type() == m_type && SIZE > mfrom.size() && (mfrom.isAddition() || mfrom.isMultiplication() || mfrom.isLogicalAnd() || mfrom.isLogicalOr())) {
2859 		bool b = true;
2860 		size_t i2 = 0;
2861 		for(size_t i = 0; i < mfrom.size(); i++) {
2862 			b = false;
2863 			for(; i2 < SIZE; i2++) {
2864 				if(CHILD(i2).equals(mfrom[i], true, true)) {b = true; break;}
2865 			}
2866 			if(!b) break;
2867 		}
2868 		if(b) {
2869 			i2 = 0;
2870 			for(size_t i = 0; i < mfrom.size(); i++) {
2871 				for(; i2 < SIZE; i2++) {
2872 					if(CHILD(i2).equals(mfrom[i], true, true)) {ERASE(i2); break;}
2873 				}
2874 			}
2875 			if(SIZE == 1) setToChild(1);
2876 			else if(SIZE == 0) clear();
2877 			else if(!once_only) replace(mfrom, mto, once_only, exclude_function_arguments);
2878 			if(mfrom.isAddition()) add(mto);
2879 			else if(mfrom.isMultiplication()) multiply(mto);
2880 			else if(mfrom.isLogicalAnd()) transform(STRUCT_LOGICAL_AND, mto);
2881 			else if(mfrom.isLogicalOr()) transform(STRUCT_LOGICAL_OR, mto);
2882 			return true;
2883 		}
2884 	}
2885 	if(exclude_function_arguments && m_type == STRUCT_FUNCTION) return false;
2886 	bool b = false;
2887 	for(size_t i = 0; i < SIZE; i++) {
2888 		if(CHILD(i).replace(mfrom, mto, once_only, exclude_function_arguments)) {
2889 			b = true;
2890 			CHILD_UPDATED(i);
2891 			if(once_only) return true;
2892 		}
2893 	}
2894 	return b;
2895 }
replace(Variable * v,const MathStructure & mto)2896 bool MathStructure::replace(Variable *v, const MathStructure &mto) {
2897 	if(b_protected) b_protected = false;
2898 	if(m_type == STRUCT_VARIABLE && o_variable == v) {
2899 		set(mto);
2900 		return true;
2901 	}
2902 	bool b = false;
2903 	for(size_t i = 0; i < SIZE; i++) {
2904 		if(CHILD(i).replace(v, mto)) {
2905 			b = true;
2906 			CHILD_UPDATED(i);
2907 		}
2908 	}
2909 	return b;
2910 }
calculateReplace(const MathStructure & mfrom,const MathStructure & mto,const EvaluationOptions & eo,bool exclude_function_arguments)2911 bool MathStructure::calculateReplace(const MathStructure &mfrom, const MathStructure &mto, const EvaluationOptions &eo, bool exclude_function_arguments) {
2912 	if(equals(mfrom, true, true)) {
2913 		set(mto);
2914 		return true;
2915 	}
2916 	if(mfrom.size() > 0 && mfrom.type() == m_type && SIZE > mfrom.size() && (mfrom.isAddition() || mfrom.isMultiplication() || mfrom.isLogicalAnd() || mfrom.isLogicalOr())) {
2917 		bool b = true;
2918 		size_t i2 = 0;
2919 		for(size_t i = 0; i < mfrom.size(); i++) {
2920 			b = false;
2921 			for(; i2 < SIZE; i2++) {
2922 				if(CHILD(i2).equals(mfrom[i], true, true)) {b = true; break;}
2923 			}
2924 			if(!b) break;
2925 		}
2926 		if(b) {
2927 			i2 = 0;
2928 			for(size_t i = 0; i < mfrom.size(); i++) {
2929 				for(; i2 < SIZE; i2++) {
2930 					if(CHILD(i2).equals(mfrom[i], true, true)) {ERASE(i2); break;}
2931 				}
2932 			}
2933 			if(SIZE == 1) setToChild(1);
2934 			else if(SIZE == 0) clear();
2935 			else calculateReplace(mfrom, mto, eo, exclude_function_arguments);
2936 			if(mfrom.isAddition()) add(mto);
2937 			else if(mfrom.isMultiplication()) multiply(mto);
2938 			else if(mfrom.isLogicalAnd()) transform(STRUCT_LOGICAL_AND, mto);
2939 			else if(mfrom.isLogicalOr()) transform(STRUCT_LOGICAL_OR, mto);
2940 			calculatesub(eo, eo, false);
2941 			return true;
2942 		}
2943 	}
2944 	if(exclude_function_arguments && m_type == STRUCT_FUNCTION) return false;
2945 	bool b = false;
2946 	for(size_t i = 0; i < SIZE; i++) {
2947 		if(CHILD(i).calculateReplace(mfrom, mto, eo, exclude_function_arguments)) {
2948 			b = true;
2949 			CHILD_UPDATED(i);
2950 		}
2951 	}
2952 	if(b) {
2953 		calculatesub(eo, eo, false);
2954 	}
2955 	return b;
2956 }
2957 
replace(const MathStructure & mfrom1,const MathStructure & mto1,const MathStructure & mfrom2,const MathStructure & mto2)2958 bool MathStructure::replace(const MathStructure &mfrom1, const MathStructure &mto1, const MathStructure &mfrom2, const MathStructure &mto2) {
2959 	if(equals(mfrom1, true, true)) {
2960 		set(mto1);
2961 		return true;
2962 	}
2963 	if(equals(mfrom2, true, true)) {
2964 		set(mto2);
2965 		return true;
2966 	}
2967 	bool b = false;
2968 	for(size_t i = 0; i < SIZE; i++) {
2969 		if(CHILD(i).replace(mfrom1, mto1, mfrom2, mto2)) {
2970 			b = true;
2971 			CHILD_UPDATED(i);
2972 		}
2973 	}
2974 	return b;
2975 }
removeType(StructureType mtype)2976 bool MathStructure::removeType(StructureType mtype) {
2977 	if(m_type == mtype || (m_type == STRUCT_POWER && CHILD(0).type() == mtype)) {
2978 		set(1);
2979 		return true;
2980 	}
2981 	bool b = false;
2982 	if(m_type == STRUCT_MULTIPLICATION) {
2983 		for(long int i = 0; i < (long int) SIZE; i++) {
2984 			if(CHILD(i).removeType(mtype)) {
2985 				if(CHILD(i).isOne()) {
2986 					ERASE(i);
2987 					i--;
2988 				} else {
2989 					CHILD_UPDATED(i);
2990 				}
2991 				b = true;
2992 			}
2993 		}
2994 		if(SIZE == 0) {
2995 			set(1);
2996 		} else if(SIZE == 1) {
2997 			setToChild(1, true);
2998 		}
2999 	} else {
3000 		if(m_type == STRUCT_FUNCTION) {
3001 			if(mtype != STRUCT_UNIT || (o_function->id() != FUNCTION_ID_SQRT && o_function->id() != FUNCTION_ID_ROOT && o_function->id() != FUNCTION_ID_CBRT)) return b;
3002 		}
3003 		for(size_t i = 0; i < SIZE; i++) {
3004 			if(CHILD(i).removeType(mtype)) {
3005 				b = true;
3006 				CHILD_UPDATED(i);
3007 			}
3008 		}
3009 	}
3010 	return b;
3011 }
3012 
find_x_var() const3013 const MathStructure &MathStructure::find_x_var() const {
3014 	if(isSymbolic()) {
3015 		return *this;
3016 	} else if(isVariable()) {
3017 		if(o_variable->isKnown()) return m_undefined;
3018 		return *this;
3019 	}
3020 	const MathStructure *mstruct;
3021 	const MathStructure *x_mstruct = &m_undefined;
3022 	for(size_t i = 0; i < SIZE; i++) {
3023 		mstruct = &CHILD(i).find_x_var();
3024 		if(mstruct->isVariable()) {
3025 			if(!((UnknownVariable*) mstruct->variable())->interval().isUndefined()) {
3026 				if(x_mstruct->isUndefined()) x_mstruct = mstruct;
3027 			} else if(mstruct->variable() == CALCULATOR->getVariableById(VARIABLE_ID_X)) {
3028 				return *mstruct;
3029 			} else if(!x_mstruct->isVariable()) {
3030 				x_mstruct = mstruct;
3031 			} else if(mstruct->variable() == CALCULATOR->getVariableById(VARIABLE_ID_Y)) {
3032 				x_mstruct = mstruct;
3033 			} else if(mstruct->variable() == CALCULATOR->getVariableById(VARIABLE_ID_Z) && x_mstruct->variable() != CALCULATOR->getVariableById(VARIABLE_ID_Y)) {
3034 				x_mstruct = mstruct;
3035 			}
3036 		} else if(mstruct->isSymbolic()) {
3037 			if(!x_mstruct->isVariable() && (!x_mstruct->isSymbolic() || x_mstruct->symbol() > mstruct->symbol())) {
3038 				x_mstruct = mstruct;
3039 			}
3040 		}
3041 	}
3042 	return *x_mstruct;
3043 }
3044 
inParentheses() const3045 bool MathStructure::inParentheses() const {return b_parentheses;}
setInParentheses(bool b)3046 void MathStructure::setInParentheses(bool b) {b_parentheses = b;}
3047 
flattenMultiplication(MathStructure & mstruct)3048 bool flattenMultiplication(MathStructure &mstruct) {
3049 	bool retval = false;
3050 	for(size_t i = 0; i < mstruct.size();) {
3051 		if(mstruct[i].isMultiplication()) {
3052 			for(size_t i2 = 0; i2 < mstruct[i].size(); i2++) {
3053 				mstruct[i][i2].ref();
3054 				mstruct.insertChild_nocopy(&mstruct[i][i2], i + i2 + 2);
3055 			}
3056 			mstruct.delChild(i + 1);
3057 			retval = true;
3058 		} else {
3059 			i++;
3060 		}
3061 	}
3062 	return retval;
3063 }
3064 
3065