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