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 "Variable.h"
15 #include "util.h"
16 #include "Calculator.h"
17 #include "MathStructure.h"
18 #include "Number.h"
19 #include "BuiltinFunctions.h"
20 
21 using std::string;
22 using std::vector;
23 
Assumptions()24 Assumptions::Assumptions() : i_type(ASSUMPTION_TYPE_NUMBER), i_sign(ASSUMPTION_SIGN_UNKNOWN), fmin(NULL), fmax(NULL), b_incl_min(true), b_incl_max(true) {}
~Assumptions()25 Assumptions::~Assumptions() {}
26 
isPositive()27 bool Assumptions::isPositive() {return i_sign == ASSUMPTION_SIGN_POSITIVE || (fmin && (fmin->isPositive() || (!b_incl_min && fmin->isNonNegative())));}
isNegative()28 bool Assumptions::isNegative() {return i_sign == ASSUMPTION_SIGN_NEGATIVE || (fmax && (fmax->isNegative() || (!b_incl_max && fmax->isNonPositive())));}
isNonNegative()29 bool Assumptions::isNonNegative() {return i_sign == ASSUMPTION_SIGN_NONNEGATIVE || i_sign == ASSUMPTION_SIGN_POSITIVE || (fmin && fmin->isNonNegative());}
isNonPositive()30 bool Assumptions::isNonPositive() {return i_sign == ASSUMPTION_SIGN_NONPOSITIVE || i_sign == ASSUMPTION_SIGN_NEGATIVE || (fmax && fmax->isNonPositive());}
isInteger()31 bool Assumptions::isInteger() {return i_type >= ASSUMPTION_TYPE_INTEGER;}
isNumber()32 bool Assumptions::isNumber() {return i_type >= ASSUMPTION_TYPE_NUMBER || fmin || fmax;}
isRational()33 bool Assumptions::isRational() {return i_type >= ASSUMPTION_TYPE_RATIONAL;}
isReal()34 bool Assumptions::isReal() {return i_type >= ASSUMPTION_TYPE_REAL || (fmin && !fmin->hasImaginaryPart()) || (fmax && !fmax->hasImaginaryPart());}
isComplex()35 bool Assumptions::isComplex() {return i_type == ASSUMPTION_TYPE_COMPLEX;}
isNonZero()36 bool Assumptions::isNonZero() {return i_sign == ASSUMPTION_SIGN_NONZERO || isPositive() || isNegative();}
isNonMatrix()37 bool Assumptions::isNonMatrix() {return i_type >= ASSUMPTION_TYPE_NONMATRIX || fmin || fmax;}
isScalar()38 bool Assumptions::isScalar() {return i_type >= ASSUMPTION_TYPE_NONMATRIX || fmin || fmax;}
39 
type()40 AssumptionType Assumptions::type() {return i_type;}
sign()41 AssumptionSign Assumptions::sign() {return i_sign;}
setType(AssumptionType ant)42 void Assumptions::setType(AssumptionType ant) {
43 	i_type = ant;
44 	if(i_type <= ASSUMPTION_TYPE_COMPLEX && i_sign != ASSUMPTION_SIGN_NONZERO) {
45 		i_sign = ASSUMPTION_SIGN_UNKNOWN;
46 	}
47 	if(i_type <= ASSUMPTION_TYPE_NONMATRIX) {
48 		if(fmax) delete fmax;
49 		if(fmin) delete fmin;
50 	}
51 }
setSign(AssumptionSign as)52 void Assumptions::setSign(AssumptionSign as) {
53 	i_sign = as;
54 	if(i_type <= ASSUMPTION_TYPE_COMPLEX && i_sign != ASSUMPTION_SIGN_NONZERO && i_sign != ASSUMPTION_SIGN_UNKNOWN) {
55 		i_type = ASSUMPTION_TYPE_REAL;
56 	}
57 }
58 
setMin(const Number * nmin)59 void Assumptions::setMin(const Number *nmin) {
60 	if(!nmin) {
61 		if(fmin) {
62 			delete fmin;
63 		}
64 		return;
65 	}
66 	if(i_type <= ASSUMPTION_TYPE_NONMATRIX) i_type = ASSUMPTION_TYPE_NUMBER;
67 	if(!fmin) {
68 		fmin = new Number(*nmin);
69 	} else {
70 		fmin->set(*nmin);
71 	}
72 }
setIncludeEqualsMin(bool include_equals)73 void Assumptions::setIncludeEqualsMin(bool include_equals) {
74 	b_incl_min = include_equals;
75 }
includeEqualsMin() const76 bool Assumptions::includeEqualsMin() const {
77 	return b_incl_min;
78 }
min() const79 const Number *Assumptions::min() const {
80 	return fmin;
81 }
setMax(const Number * nmax)82 void Assumptions::setMax(const Number *nmax) {
83 	if(!nmax) {
84 		if(fmax) {
85 			delete fmax;
86 		}
87 		return;
88 	}
89 	if(i_type <= ASSUMPTION_TYPE_NONMATRIX) i_type = ASSUMPTION_TYPE_NUMBER;
90 	if(!fmax) {
91 		fmax = new Number(*nmax);
92 	} else {
93 		fmax->set(*nmax);
94 	}
95 }
setIncludeEqualsMax(bool include_equals)96 void Assumptions::setIncludeEqualsMax(bool include_equals) {
97 	b_incl_max = include_equals;
98 }
includeEqualsMax() const99 bool Assumptions::includeEqualsMax() const {
100 	return b_incl_max;
101 }
max() const102 const Number *Assumptions::max() const {
103 	return fmax;
104 }
105 
106 
Variable(string cat_,string name_,string title_,bool is_local,bool is_builtin,bool is_active)107 Variable::Variable(string cat_, string name_, string title_, bool is_local, bool is_builtin, bool is_active) : ExpressionItem(cat_, name_, title_, "", is_local, is_builtin, is_active) {
108 	setChanged(false);
109 }
Variable()110 Variable::Variable() : ExpressionItem() {}
Variable(const Variable * variable)111 Variable::Variable(const Variable *variable) {set(variable);}
~Variable()112 Variable::~Variable() {}
set(const ExpressionItem * item)113 void Variable::set(const ExpressionItem *item) {
114 	ExpressionItem::set(item);
115 }
116 
117 
UnknownVariable(string cat_,string name_,string title_,bool is_local,bool is_builtin,bool is_active)118 UnknownVariable::UnknownVariable(string cat_, string name_, string title_, bool is_local, bool is_builtin, bool is_active) : Variable(cat_, name_, title_, is_local, is_builtin, is_active) {
119 	setChanged(false);
120 	o_assumption = NULL;
121 	mstruct = NULL;
122 }
UnknownVariable()123 UnknownVariable::UnknownVariable() : Variable() {
124 	o_assumption = NULL;
125 	mstruct = NULL;
126 }
UnknownVariable(const UnknownVariable * variable)127 UnknownVariable::UnknownVariable(const UnknownVariable *variable) {
128 	mstruct = NULL;
129 	o_assumption = NULL;
130 	set(variable);
131 }
~UnknownVariable()132 UnknownVariable::~UnknownVariable() {
133 	if(o_assumption) delete o_assumption;
134 	if(mstruct) mstruct->unref();
135 }
copy() const136 ExpressionItem *UnknownVariable::copy() const {
137 	return new UnknownVariable(this);
138 }
set(const ExpressionItem * item)139 void UnknownVariable::set(const ExpressionItem *item) {
140 	if(item->type() == TYPE_VARIABLE && item->subtype() == SUBTYPE_UNKNOWN_VARIABLE) {
141 		if(o_assumption) delete o_assumption;
142 		o_assumption = ((UnknownVariable*) item)->assumptions();
143 		if(((UnknownVariable*) item)->interval().isUndefined()) {
144 			if(mstruct) mstruct->unref();
145 			mstruct = NULL;
146 		} else {
147 			if(mstruct) mstruct->set(((UnknownVariable*) item)->interval());
148 			else mstruct = new MathStructure(((UnknownVariable*) item)->interval());
149 		}
150 	}
151 	ExpressionItem::set(item);
152 }
setAssumptions(Assumptions * ass)153 void UnknownVariable::setAssumptions(Assumptions *ass) {
154 	if(o_assumption) delete o_assumption;
155 	o_assumption = ass;
156 }
setAssumptions(const MathStructure & mvar)157 void UnknownVariable::setAssumptions(const MathStructure &mvar) {
158 	Assumptions *ass = new Assumptions();
159 	if(mvar.representsInteger(true)) ass->setType(ASSUMPTION_TYPE_INTEGER);
160 	else if(mvar.representsRational(true)) ass->setType(ASSUMPTION_TYPE_RATIONAL);
161 	else if(mvar.representsReal(true)) ass->setType(ASSUMPTION_TYPE_REAL);
162 	else if(mvar.representsComplex(true)) ass->setType(ASSUMPTION_TYPE_COMPLEX);
163 	else if(mvar.representsNumber(true)) ass->setType(ASSUMPTION_TYPE_NUMBER);
164 	else if(mvar.representsNonMatrix()) ass->setType(ASSUMPTION_TYPE_NONMATRIX);
165 	if(mvar.representsPositive(true)) ass->setSign(ASSUMPTION_SIGN_POSITIVE);
166 	else if(mvar.representsNegative(true)) ass->setSign(ASSUMPTION_SIGN_NEGATIVE);
167 	else if(mvar.representsNonPositive(true)) ass->setSign(ASSUMPTION_SIGN_NONPOSITIVE);
168 	else if(mvar.representsNonNegative(true)) ass->setSign(ASSUMPTION_SIGN_NONNEGATIVE);
169 	else if(mvar.representsNonZero(true)) ass->setSign(ASSUMPTION_SIGN_NONZERO);
170 	if(o_assumption) delete o_assumption;
171 	o_assumption = ass;
172 }
assumptions()173 Assumptions *UnknownVariable::assumptions() {
174 	return o_assumption;
175 }
interval() const176 const MathStructure &UnknownVariable::interval() const {
177 	if(mstruct) return *mstruct;
178 	return m_undefined;
179 }
setInterval(const MathStructure & o)180 void UnknownVariable::setInterval(const MathStructure &o) {
181 	setAssumptions(o);
182 	if(o.isUndefined()) {
183 		if(mstruct) mstruct->unref();
184 		mstruct = NULL;
185 	} else {
186 		if(mstruct) mstruct->set(o);
187 		else mstruct = new MathStructure(o);
188 		if(!o_assumption->isReal() && (o.isNumber() && o.number().isInterval() && !o.number().lowerEndPoint().hasImaginaryPart() && !o.number().upperEndPoint().hasImaginaryPart())) o_assumption->setType(ASSUMPTION_TYPE_REAL);
189 		else if(!o_assumption->isNumber() && o.isNumber() && o.number().isInterval()) o_assumption->setType(ASSUMPTION_TYPE_NUMBER);
190 	}
191 }
representsPositive(bool b)192 bool UnknownVariable::representsPositive(bool b) {
193 	if(!b && mstruct) return mstruct->representsPositive(false);
194 	if(o_assumption) return o_assumption->isPositive();
195 	return CALCULATOR->defaultAssumptions()->isPositive();
196 }
representsNegative(bool b)197 bool UnknownVariable::representsNegative(bool b) {
198 	if(!b && mstruct) return mstruct->representsNegative(false);
199 	if(o_assumption) return o_assumption->isNegative();
200 	return CALCULATOR->defaultAssumptions()->isNegative();
201 }
representsNonNegative(bool b)202 bool UnknownVariable::representsNonNegative(bool b) {
203 	if(!b && mstruct) return mstruct->representsNonNegative(false);
204 	if(o_assumption) return o_assumption->isNonNegative();
205 	return CALCULATOR->defaultAssumptions()->isNonNegative();
206 }
representsNonPositive(bool b)207 bool UnknownVariable::representsNonPositive(bool b) {
208 	if(!b && mstruct) return mstruct->representsNonPositive(false);
209 	if(o_assumption) return o_assumption->isNonPositive();
210 	return CALCULATOR->defaultAssumptions()->isNonPositive();
211 }
representsInteger(bool b)212 bool UnknownVariable::representsInteger(bool b) {
213 	if(!b && mstruct) return mstruct->representsInteger(false);
214 	if(o_assumption) return o_assumption->isInteger();
215 	return CALCULATOR->defaultAssumptions()->isInteger();
216 }
representsNumber(bool b)217 bool UnknownVariable::representsNumber(bool b) {
218 	if(!b && mstruct) return mstruct->representsNumber(false);
219 	if(o_assumption) return o_assumption->isNumber();
220 	return CALCULATOR->defaultAssumptions()->isNumber();
221 }
representsRational(bool b)222 bool UnknownVariable::representsRational(bool b) {
223 	if(!b && mstruct) return mstruct->representsRational(false);
224 	if(o_assumption) return o_assumption->isRational();
225 	return CALCULATOR->defaultAssumptions()->isRational();
226 }
representsReal(bool b)227 bool UnknownVariable::representsReal(bool b) {
228 	if(!b && mstruct) return mstruct->representsReal(false);
229 	if(o_assumption) return o_assumption->isReal();
230 	return CALCULATOR->defaultAssumptions()->isReal();
231 }
representsNonComplex(bool b)232 bool UnknownVariable::representsNonComplex(bool b) {
233 	if(mstruct && (!b || (!o_assumption || (!o_assumption->isReal() && !o_assumption->isComplex())))) return mstruct->representsNonComplex(b);
234 	if(o_assumption) return o_assumption->isReal();
235 	return CALCULATOR->defaultAssumptions()->isReal();
236 }
representsComplex(bool b)237 bool UnknownVariable::representsComplex(bool b) {
238 	if(!b && mstruct) return mstruct->representsComplex(false);
239 	if(o_assumption) return o_assumption->isComplex();
240 	return CALCULATOR->defaultAssumptions()->isComplex();
241 }
representsNonZero(bool b)242 bool UnknownVariable::representsNonZero(bool b) {
243 	if(!b && mstruct) return mstruct->representsNonZero(false);
244 	if(o_assumption) return o_assumption->isNonZero();
245 	return CALCULATOR->defaultAssumptions()->isNonZero();
246 }
representsNonMatrix()247 bool UnknownVariable::representsNonMatrix() {
248 	if(o_assumption) return o_assumption->isNonMatrix();
249 	return CALCULATOR->defaultAssumptions()->isNonMatrix();
250 }
representsScalar()251 bool UnknownVariable::representsScalar() {
252 	if(o_assumption) return o_assumption->isScalar();
253 	return CALCULATOR->defaultAssumptions()->isScalar();
254 }
255 
KnownVariable(string cat_,string name_,const MathStructure & o,string title_,bool is_local,bool is_builtin,bool is_active)256 KnownVariable::KnownVariable(string cat_, string name_, const MathStructure &o, string title_, bool is_local, bool is_builtin, bool is_active) : Variable(cat_, name_, title_, is_local, is_builtin, is_active) {
257 	mstruct = new MathStructure(o); mstruct_alt = NULL;
258 	setApproximate(mstruct->isApproximate());
259 	setPrecision(mstruct->precision());
260 	b_expression = false;
261 	sexpression = "";
262 	suncertainty = "";
263 	b_relative_uncertainty = false;
264 	sunit = "";
265 	calculated_precision = -1;
266 	setChanged(false);
267 }
KnownVariable(string cat_,string name_,string expression_,string title_,bool is_local,bool is_builtin,bool is_active)268 KnownVariable::KnownVariable(string cat_, string name_, string expression_, string title_, bool is_local, bool is_builtin, bool is_active) : Variable(cat_, name_, title_, is_local, is_builtin, is_active) {
269 	mstruct = NULL; mstruct_alt = NULL;
270 	calculated_precision = -1;
271 	suncertainty = "";
272 	b_relative_uncertainty = false;
273 	sunit = "";
274 	set(expression_);
275 	setChanged(false);
276 }
KnownVariable()277 KnownVariable::KnownVariable() : Variable() {
278 	mstruct = NULL; mstruct_alt = NULL;
279 }
KnownVariable(const KnownVariable * variable)280 KnownVariable::KnownVariable(const KnownVariable *variable) {
281 	mstruct = NULL; mstruct_alt = NULL;
282 	set(variable);
283 }
~KnownVariable()284 KnownVariable::~KnownVariable() {
285 	if(mstruct) delete mstruct;
286 	if(mstruct_alt) delete mstruct_alt;
287 }
copy() const288 ExpressionItem *KnownVariable::copy() const {
289 	return new KnownVariable(this);
290 }
isExpression() const291 bool KnownVariable::isExpression() const {
292 	return b_expression;
293 }
expression() const294 string KnownVariable::expression() const {
295 	return sexpression;
296 }
uncertainty(bool * is_relative) const297 string KnownVariable::uncertainty(bool *is_relative) const {
298 	if(is_relative) *is_relative = b_relative_uncertainty;
299 	return suncertainty;
300 }
unit() const301 string KnownVariable::unit() const {
302 	return sunit;
303 }
set(const ExpressionItem * item)304 void KnownVariable::set(const ExpressionItem *item) {
305 	if(item->type() == TYPE_VARIABLE && item->subtype() == SUBTYPE_KNOWN_VARIABLE) {
306 		calculated_precision = -1;
307 		sexpression = ((KnownVariable*) item)->expression();
308 		suncertainty = ((KnownVariable*) item)->uncertainty(&b_relative_uncertainty);
309 		sunit = ((KnownVariable*) item)->unit();
310 		b_expression = ((KnownVariable*) item)->isExpression();
311 		if(!b_expression) {
312 			set(((KnownVariable*) item)->get());
313 		} else {
314 			if(mstruct) delete mstruct;
315 			if(mstruct_alt) delete mstruct_alt;
316 			mstruct = NULL;
317 			mstruct_alt = NULL;
318 		}
319 	}
320 	ExpressionItem::set(item);
321 }
set(const MathStructure & o)322 void KnownVariable::set(const MathStructure &o) {
323 	if(!mstruct) mstruct = new MathStructure(o);
324 	else mstruct->set(o);
325 	if(mstruct_alt) delete mstruct_alt;
326 	mstruct_alt = NULL;
327 	setApproximate(mstruct->isApproximate());
328 	setPrecision(mstruct->precision());
329 	calculated_precision = -1;
330 	b_expression = false;
331 	sexpression = "";
332 	setApproximate(o.isApproximate());
333 	setChanged(true);
334 }
set(string expression_)335 void KnownVariable::set(string expression_) {
336 	if(mstruct) delete mstruct;
337 	if(mstruct_alt) delete mstruct_alt;
338 	mstruct = NULL;
339 	mstruct_alt = NULL;
340 	b_expression = true;
341 	sexpression = expression_;
342 	remove_blank_ends(sexpression);
343 	calculated_precision = -1;
344 	setChanged(true);
345 }
setUncertainty(string standard_uncertainty,bool is_relative)346 void KnownVariable::setUncertainty(string standard_uncertainty, bool is_relative) {
347 	if(mstruct) delete mstruct;
348 	if(mstruct_alt) delete mstruct_alt;
349 	mstruct = NULL;
350 	mstruct_alt = NULL;
351 	suncertainty = standard_uncertainty;
352 	b_relative_uncertainty = is_relative;
353 	remove_blank_ends(suncertainty);
354 	calculated_precision = -1;
355 	if(!suncertainty.empty()) setApproximate(true);
356 	setChanged(true);
357 }
setUnit(string unit_expression)358 void KnownVariable::setUnit(string unit_expression) {
359 	if(mstruct) delete mstruct;
360 	if(mstruct_alt) delete mstruct_alt;
361 	mstruct = NULL;
362 	mstruct_alt = NULL;
363 	sunit = unit_expression;
364 	remove_blank_ends(sunit);
365 	calculated_precision = -1;
366 	setChanged(true);
367 }
set_precision_of_numbers(MathStructure & mstruct,int i_prec)368 bool set_precision_of_numbers(MathStructure &mstruct, int i_prec) {
369 	if(mstruct.isNumber()) {
370 		if(i_prec < 0) {
371 			if(!mstruct.number().isApproximate()) {
372 				mstruct.number().setApproximate();
373 				mstruct.numberUpdated();
374 			}
375 		} else if(mstruct.number().precision() < 0 || mstruct.number().precision() < i_prec) {
376 			mstruct.number().setPrecision(i_prec);
377 			mstruct.numberUpdated();
378 		}
379 		return true;
380 	}
381 	bool b = false;
382 	for(size_t i = 0; i < mstruct.size(); i++) {
383 		if(set_precision_of_numbers(mstruct[i], i_prec)) {
384 			mstruct.childUpdated(i + 1);
385 			b = true;
386 		}
387 	}
388 	return b;
389 }
390 extern bool set_uncertainty(MathStructure &mstruct, MathStructure &munc, const EvaluationOptions &eo = default_evaluation_options, bool do_eval = false);
391 extern bool create_interval(MathStructure &mstruct, const MathStructure &m1, const MathStructure &m2);
replace_f_interval(MathStructure & mstruct)392 bool replace_f_interval(MathStructure &mstruct) {
393 	if(mstruct.isFunction() && mstruct.function()->id() == FUNCTION_ID_INTERVAL && mstruct.size() == 2) {
394 		if(mstruct[0].isNumber() && mstruct[1].isNumber()) {
395 			Number nr;
396 			if(nr.setInterval(mstruct[0].number(), mstruct[1].number())) {
397 				mstruct.set(nr, true);
398 				return true;
399 			}
400 		} else {
401 			MathStructure m1(mstruct[0]);
402 			MathStructure m2(mstruct[1]);
403 			if(create_interval(mstruct, m1, m2)) return true;
404 		}
405 	} else if(mstruct.isFunction() && mstruct.function()->id() == FUNCTION_ID_UNCERTAINTY && mstruct.size() == 3 && mstruct[2].isNumber()) {
406 		bool b_rel = mstruct[2].number().getBoolean();
407 		if(mstruct[0].isNumber() && mstruct[1].isNumber()) {
408 			Number nr(mstruct[0].number());
409 			if(b_rel) nr.setRelativeUncertainty(mstruct[1].number());
410 			else nr.setUncertainty(mstruct[1].number());
411 			mstruct.set(nr, true);
412 			return true;
413 		} else if(!b_rel) {
414 			MathStructure m1(mstruct[0]);
415 			MathStructure m2(mstruct[1]);
416 			if(set_uncertainty(m1, m2)) {mstruct = m1; return true;}
417 		}
418 	} else {
419 		bool b = false;
420 		for(size_t i = 0; i < mstruct.size(); i++) {
421 			if(replace_f_interval(mstruct[i])) {
422 				mstruct.childUpdated(i + 1);
423 				b = true;
424 			}
425 		}
426 		return b;
427 	}
428 	return false;
429 }
get()430 const MathStructure &KnownVariable::get() {
431 	MathStructure *m = mstruct;
432 	if(b_expression && !CALCULATOR->variableUnitsEnabled() && !sunit.empty()) m = mstruct_alt;
433 	if(b_expression && (!m || m->isAborted())) {
434 		if(m) m->unref();
435 		if(!CALCULATOR->variableUnitsEnabled() && !sunit.empty()) {
436 			mstruct_alt = new MathStructure();
437 			m = mstruct_alt;
438 		} else {
439 			mstruct = new MathStructure();
440 			m = mstruct;
441 		}
442 		ParseOptions po;
443 		if(isApproximate() && precision() == -1 && suncertainty.empty()) {
444 			po.read_precision = ALWAYS_READ_PRECISION;
445 		}
446 		bool b_number = false;
447 		if(!suncertainty.empty()) {
448 			b_number = true;
449 		} else {
450 			size_t i = sexpression.rfind(')');
451 			if(i != string::npos && i > 2 && (i == sexpression.length() - 1 || (i < sexpression.length() - 2 && (sexpression[i + 1] == 'E' || sexpression[i + 1] == 'e')))) {
452 				size_t i2 = sexpression.rfind('(');
453 				if(i2 != string::npos && i2 < i - 1) {
454 					if(sexpression.find_first_not_of(NUMBER_ELEMENTS SPACES, sexpression[0] == '-' || sexpression[0] == '+' ? 1 : 0) == i2 && sexpression.find_first_not_of(NUMBERS SPACES, i2 + 1) == i && (i == sexpression.length() - 1 || sexpression.find_first_not_of(NUMBER_ELEMENTS SPACES, sexpression[i + 2] == '-' || sexpression[i + 2] == '+' ? i + 3 : i + 2) == string::npos)) {
455 						b_number = true;
456 					}
457 				}
458 			}
459 		}
460 		if(b_number) {
461 			m->number().set(sexpression, po);
462 			m->numberUpdated();
463 		} else {
464 			m->setAborted();
465 			CALCULATOR->parse(m, sexpression, po);
466 		}
467 		if(!sunit.empty() && (!CALCULATOR->variableUnitsEnabled() || sunit != "auto")) {
468 			m->removeType(STRUCT_UNIT);
469 			if(m->containsType(STRUCT_UNIT, false, true, true) != 0) m->transformById(FUNCTION_ID_STRIP_UNITS);
470 		}
471 		if(!suncertainty.empty()) {
472 			Number nr_u(suncertainty);
473 			if(m->isNumber()) {
474 				if(b_relative_uncertainty) m->number().setRelativeUncertainty(nr_u);
475 				else m->number().setUncertainty(nr_u);
476 				m->numberUpdated();
477 			} else if(m->isMultiplication() && m->size() > 0 && (*m)[0].isNumber()) {
478 				if(b_relative_uncertainty) (*m)[0].number().setRelativeUncertainty(nr_u);
479 				else (*m)[0].number().setUncertainty(nr_u);
480 				(*m)[0].numberUpdated();
481 				m->childUpdated(1);
482 			}
483 		} else if(precision() >= 0) {
484 			if(m->precision() < 0 || precision() < m->precision()) {
485 				if(!set_precision_of_numbers(*m, precision())) m->setPrecision(precision(), true);
486 			}
487 		} else if(isApproximate()) {
488 			if(!m->isApproximate()) {
489 				if(!set_precision_of_numbers(*m, precision())) m->setApproximate(true, true);
490 			}
491 		}
492 		if(!sunit.empty() && CALCULATOR->variableUnitsEnabled() && sunit != "auto") {
493 			MathStructure *m_unit = new MathStructure;
494 			m_unit->setAborted();
495 			CALCULATOR->parse(m_unit, sunit, po);
496 			m->multiply_nocopy(m_unit);
497 		}
498 		//m->unformat();
499 		replace_f_interval(*m);
500 	}
501 	if(m->contains(this, false, true, true) > 0) {
502 		CALCULATOR->error(true, _("Recursive variable: %s = %s"), name().c_str(), m->print().c_str(), NULL);
503 		return m_undefined;
504 	}
505 	return *m;
506 }
representsPositive(bool allow_units)507 bool KnownVariable::representsPositive(bool allow_units) {return get().representsPositive(allow_units);}
representsNegative(bool allow_units)508 bool KnownVariable::representsNegative(bool allow_units) {return get().representsNegative(allow_units);}
representsNonNegative(bool allow_units)509 bool KnownVariable::representsNonNegative(bool allow_units) {return get().representsNonNegative(allow_units);}
representsNonPositive(bool allow_units)510 bool KnownVariable::representsNonPositive(bool allow_units) {return get().representsNonPositive(allow_units);}
representsInteger(bool allow_units)511 bool KnownVariable::representsInteger(bool allow_units) {return get().representsInteger(allow_units);}
representsNonInteger(bool allow_units)512 bool KnownVariable::representsNonInteger(bool allow_units) {return get().representsNonInteger(allow_units);}
representsFraction(bool allow_units)513 bool KnownVariable::representsFraction(bool allow_units) {return get().representsFraction(allow_units);}
representsNumber(bool allow_units)514 bool KnownVariable::representsNumber(bool allow_units) {return get().representsNumber(allow_units);}
representsRational(bool allow_units)515 bool KnownVariable::representsRational(bool allow_units) {return get().representsRational(allow_units);}
representsReal(bool allow_units)516 bool KnownVariable::representsReal(bool allow_units) {return get().representsReal(allow_units);}
representsNonComplex(bool allow_units)517 bool KnownVariable::representsNonComplex(bool allow_units) {return get().representsNonComplex(allow_units);}
representsComplex(bool allow_units)518 bool KnownVariable::representsComplex(bool allow_units) {return get().representsComplex(allow_units);}
representsNonZero(bool allow_units)519 bool KnownVariable::representsNonZero(bool allow_units) {return get().representsNonZero(allow_units);}
representsEven(bool allow_units)520 bool KnownVariable::representsEven(bool allow_units) {return get().representsEven(allow_units);}
representsOdd(bool allow_units)521 bool KnownVariable::representsOdd(bool allow_units) {return get().representsOdd(allow_units);}
representsUndefined(bool include_childs,bool include_infinite,bool be_strict)522 bool KnownVariable::representsUndefined(bool include_childs, bool include_infinite, bool be_strict) {return get().representsUndefined(include_childs, include_infinite, be_strict);}
representsBoolean()523 bool KnownVariable::representsBoolean() {return get().representsBoolean();}
representsNonMatrix()524 bool KnownVariable::representsNonMatrix() {return get().representsNonMatrix();}
representsScalar()525 bool KnownVariable::representsScalar() {return get().representsScalar();}
526 
DynamicVariable(string cat_,string name_,string title_,bool is_local,bool is_builtin,bool is_active)527 DynamicVariable::DynamicVariable(string cat_, string name_, string title_, bool is_local, bool is_builtin, bool is_active) : KnownVariable(cat_, name_, MathStructure(), title_, is_local, is_builtin, is_active) {
528 	mstruct = NULL; mstruct_alt = NULL;
529 	calculated_precision = -1;
530 	always_recalculate = false;
531 	setApproximate();
532 	setChanged(false);
533 }
DynamicVariable(const DynamicVariable * variable)534 DynamicVariable::DynamicVariable(const DynamicVariable *variable) {
535 	mstruct = NULL; mstruct_alt = NULL;
536 	set(variable);
537 	setApproximate();
538 	setChanged(false);
539 	always_recalculate = false;
540 }
DynamicVariable()541 DynamicVariable::DynamicVariable() : KnownVariable() {
542 	mstruct = NULL; mstruct_alt = NULL;
543 	calculated_precision = -1;
544 	setApproximate();
545 	setChanged(false);
546 	always_recalculate = false;
547 }
~DynamicVariable()548 DynamicVariable::~DynamicVariable() {
549 	if(mstruct) delete mstruct;
550 	if(mstruct_alt) delete mstruct_alt;
551 }
set(const ExpressionItem * item)552 void DynamicVariable::set(const ExpressionItem *item) {
553 	ExpressionItem::set(item);
554 }
set(const MathStructure &)555 void DynamicVariable::set(const MathStructure&) {}
set(string)556 void DynamicVariable::set(string) {}
get()557 const MathStructure &DynamicVariable::get() {
558 	MathStructure *m = mstruct;
559 	if(!always_recalculate && !CALCULATOR->usesIntervalArithmetic()) m = mstruct_alt;
560 	if(always_recalculate || calculated_precision != CALCULATOR->getPrecision() || !m || m->isAborted()) {
561 		if(m) {
562 			if(mstruct) {mstruct->unref(); mstruct = NULL;}
563 			if(mstruct_alt) {mstruct_alt->unref(); mstruct_alt = NULL;}
564 		}
565 		if(!always_recalculate && !CALCULATOR->usesIntervalArithmetic()) {
566 			mstruct_alt = new MathStructure();
567 			mstruct_alt->setAborted();
568 			m = mstruct_alt;
569 		} else {
570 			mstruct = new MathStructure();
571 			mstruct->setAborted();
572 			m = mstruct;
573 		}
574 		calculated_precision = CALCULATOR->getPrecision();
575 		calculate(*m);
576 	}
577 	return *m;
578 }
calculatedPrecision() const579 int DynamicVariable::calculatedPrecision() const {
580 	return calculated_precision;
581 }
582 
PiVariable()583 PiVariable::PiVariable() : DynamicVariable("Constants", "pi") {}
calculate(MathStructure & m) const584 void PiVariable::calculate(MathStructure &m) const {
585 	Number nr; nr.pi(); m.set(nr);
586 }
EVariable()587 EVariable::EVariable() : DynamicVariable("Constants", "e") {}
calculate(MathStructure & m) const588 void EVariable::calculate(MathStructure &m) const {
589 	Number nr; nr.e(); m.set(nr);
590 }
EulerVariable()591 EulerVariable::EulerVariable() : DynamicVariable("Constants", "euler") {}
calculate(MathStructure & m) const592 void EulerVariable::calculate(MathStructure &m) const {
593 	Number nr; nr.euler(); m.set(nr);
594 }
CatalanVariable()595 CatalanVariable::CatalanVariable() : DynamicVariable("Constants", "catalan") {}
calculate(MathStructure & m) const596 void CatalanVariable::calculate(MathStructure &m) const {
597 	Number nr; nr.catalan(); m.set(nr);
598 }
PrecisionVariable()599 PrecisionVariable::PrecisionVariable() : DynamicVariable("", "precision") {
600 	setApproximate(false);
601 }
calculate(MathStructure & m) const602 void PrecisionVariable::calculate(MathStructure &m) const {
603 	m.set(PRECISION, 1, 0);
604 }
605 
TodayVariable()606 TodayVariable::TodayVariable() : DynamicVariable("", "today") {
607 	setApproximate(false);
608 	always_recalculate = true;
609 }
calculate(MathStructure & m) const610 void TodayVariable::calculate(MathStructure &m) const {
611 	QalculateDateTime dt;
612 	dt.setToCurrentDate();
613 	m.set(dt);
614 }
YesterdayVariable()615 YesterdayVariable::YesterdayVariable() : DynamicVariable("", "yesterday") {
616 	setApproximate(false);
617 	always_recalculate = true;
618 }
calculate(MathStructure & m) const619 void YesterdayVariable::calculate(MathStructure &m) const {
620 	QalculateDateTime dt;
621 	dt.setToCurrentDate();
622 	dt.addDays(-1);
623 	m.set(dt);
624 }
TomorrowVariable()625 TomorrowVariable::TomorrowVariable() : DynamicVariable("", "tomorrow") {
626 	setApproximate(false);
627 	always_recalculate = true;
628 }
calculate(MathStructure & m) const629 void TomorrowVariable::calculate(MathStructure &m) const {
630 	QalculateDateTime dt;
631 	dt.setToCurrentDate();
632 	dt.addDays(1);
633 	m.set(dt);
634 }
NowVariable()635 NowVariable::NowVariable() : DynamicVariable("", "now") {
636 	setApproximate(false);
637 	always_recalculate = true;
638 }
calculate(MathStructure & m) const639 void NowVariable::calculate(MathStructure &m) const {
640 	QalculateDateTime dt;
641 	dt.setToCurrentTime();
642 	m.set(dt);
643 }
644 
645 #ifdef __linux__
646 #	include <sys/sysinfo.h>
647 #endif
648 
649 #if defined __linux__ || defined _WIN32
650 
651 #include <fstream>
652 
calculate(MathStructure & m) const653 void UptimeVariable:: calculate(MathStructure &m) const {
654 	Number nr;
655 #	ifdef __linux__
656 	std::ifstream proc_uptime("/proc/uptime", std::ios::in);
657 	if(proc_uptime.is_open()) {
658 		string s_uptime;
659 		getline(proc_uptime, s_uptime, ' ');
660 		nr.set(s_uptime);
661 	} else {
662 		struct sysinfo sf;
663 		if(!sysinfo(&sf)) nr = (long int) sf.uptime;
664 	}
665 #	elif _WIN32
666 	ULONGLONG i_uptime = GetTickCount64();
667 	nr.set((long int) (i_uptime % 1000), 1000);
668 	nr += (long int) (i_uptime / 1000);
669 #	endif
670 	m = nr;
671 	Unit *u = CALCULATOR->getUnit("s");
672 	if(u) m *= u;
673 }
UptimeVariable()674 UptimeVariable::UptimeVariable() : DynamicVariable("", "uptime") {
675 	setApproximate(false);
676 	always_recalculate = true;
677 }
UptimeVariable(const UptimeVariable * variable)678 UptimeVariable::UptimeVariable(const UptimeVariable *variable) {set(variable);}
copy() const679 ExpressionItem *UptimeVariable::copy() const {return new UptimeVariable(this);}
680 #endif
681 
682