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