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 "MathStructure.h"
15 #include "Calculator.h"
16 #include "BuiltinFunctions.h"
17 #include "Number.h"
18 #include "Function.h"
19 #include "Variable.h"
20 #include "Unit.h"
21 #include "Prefix.h"
22 #include "MathStructure-support.h"
23
24 using std::string;
25 using std::cout;
26 using std::vector;
27 using std::endl;
28
gatherInformation(const MathStructure & mstruct,vector<Unit * > & base_units,vector<AliasUnit * > & alias_units,bool check_variables=false)29 void gatherInformation(const MathStructure &mstruct, vector<Unit*> &base_units, vector<AliasUnit*> &alias_units, bool check_variables = false) {
30 switch(mstruct.type()) {
31 case STRUCT_UNIT: {
32 switch(mstruct.unit()->subtype()) {
33 case SUBTYPE_BASE_UNIT: {
34 for(size_t i = 0; i < base_units.size(); i++) {
35 if(base_units[i] == mstruct.unit()) {
36 return;
37 }
38 }
39 base_units.push_back(mstruct.unit());
40 break;
41 }
42 case SUBTYPE_ALIAS_UNIT: {
43 for(size_t i = 0; i < alias_units.size(); i++) {
44 if(alias_units[i] == mstruct.unit()) {
45 return;
46 }
47 }
48 alias_units.push_back((AliasUnit*) (mstruct.unit()));
49 break;
50 }
51 case SUBTYPE_COMPOSITE_UNIT: {
52 gatherInformation(((CompositeUnit*) (mstruct.unit()))->generateMathStructure(), base_units, alias_units, check_variables);
53 break;
54 }
55 }
56 break;
57 }
58 case STRUCT_VARIABLE: {
59 if(check_variables && mstruct.variable()->isKnown()) gatherInformation(((KnownVariable*) mstruct.variable())->get(), base_units, alias_units, check_variables);
60 break;
61 }
62 case STRUCT_FUNCTION: {
63 if(mstruct.function()->id() == FUNCTION_ID_STRIP_UNITS) break;
64 for(size_t i = 0; i < mstruct.size(); i++) {
65 if(!mstruct.function()->getArgumentDefinition(i + 1) || mstruct.function()->getArgumentDefinition(i + 1)->type() != ARGUMENT_TYPE_ANGLE) {
66 gatherInformation(mstruct[i], base_units, alias_units, check_variables);
67 }
68 }
69 break;
70 }
71 default: {
72 for(size_t i = 0; i < mstruct.size(); i++) {
73 gatherInformation(mstruct[i], base_units, alias_units, check_variables);
74 }
75 break;
76 }
77 }
78
79 }
80
isUnitCompatible(const MathStructure & mstruct) const81 int MathStructure::isUnitCompatible(const MathStructure &mstruct) const {
82 if(!isMultiplication() && mstruct.isMultiplication()) return mstruct.isUnitCompatible(*this);
83 int b1 = mstruct.containsRepresentativeOfType(STRUCT_UNIT, true, true);
84 int b2 = containsRepresentativeOfType(STRUCT_UNIT, true, true);
85 if(b1 < 0 || b2 < 0) return -1;
86 if(b1 != b2) return false;
87 if(!b1) return true;
88 if(isMultiplication()) {
89 size_t unit_count1 = 0, unit_count2 = 0;
90 for(size_t i = 0; i < SIZE; i++) {
91 if(CHILD(i).isUnit_exp()) unit_count1++;
92 else if(CHILD(i).containsRepresentativeOfType(STRUCT_UNIT, true, true) != 0) return -1;
93 }
94 if(mstruct.isMultiplication()) {
95 for(size_t i = 0; i < mstruct.size(); i++) {
96 if(mstruct[i].isUnit_exp()) unit_count2++;
97 else if(mstruct[i].containsRepresentativeOfType(STRUCT_UNIT, true, true) != 0) return -1;
98 }
99 } else if(mstruct.isUnit_exp()) {
100 if(unit_count1 > 1) return false;
101 for(size_t i = 0; i < SIZE; i++) {
102 if(CHILD(i).isUnit_exp()) return CHILD(1) == mstruct;
103 }
104 } else {
105 return -1;
106 }
107 if(unit_count1 != unit_count2) return false;
108 size_t i2 = 0;
109 for(size_t i = 0; i < SIZE; i++) {
110 if(CHILD(i).isUnit_exp()) {
111 for(; i2 < mstruct.size(); i2++) {
112 if(mstruct[i2].isUnit_exp()) {
113 if(CHILD(i) != mstruct[i2]) return false;
114 i2++;
115 break;
116 }
117 }
118 }
119 }
120 } else if(isUnit_exp()) {
121 if(mstruct.isUnit_exp()) return equals(mstruct);
122 }
123 return -1;
124 }
125
syncUnits(bool sync_nonlinear_relations,bool * found_nonlinear_relations,bool calculate_new_functions,const EvaluationOptions & feo)126 bool MathStructure::syncUnits(bool sync_nonlinear_relations, bool *found_nonlinear_relations, bool calculate_new_functions, const EvaluationOptions &feo) {
127 if(SIZE == 0) return false;
128 vector<Unit*> base_units;
129 vector<AliasUnit*> alias_units;
130 vector<CompositeUnit*> composite_units;
131 gatherInformation(*this, base_units, alias_units);
132 if(alias_units.empty() || base_units.size() + alias_units.size() == 1) return false;
133 CompositeUnit *cu;
134 bool b = false, do_erase = false;
135 for(size_t i = 0; i < alias_units.size(); ) {
136 do_erase = false;
137 if(alias_units[i]->baseUnit()->subtype() == SUBTYPE_COMPOSITE_UNIT) {
138 b = false;
139 cu = (CompositeUnit*) alias_units[i]->baseUnit();
140 for(size_t i2 = 0; i2 < base_units.size(); i2++) {
141 if(cu->containsRelativeTo(base_units[i2])) {
142 for(size_t i3 = 0; i3 < composite_units.size(); i3++) {
143 if(composite_units[i3] == cu) {
144 b = true;
145 break;
146 }
147 }
148 if(!b) composite_units.push_back(cu);
149 do_erase = true;
150 break;
151 }
152 }
153 for(size_t i2 = 0; !do_erase && i2 < alias_units.size(); i2++) {
154 if(i != i2 && alias_units[i2]->baseUnit() != cu && cu->containsRelativeTo(alias_units[i2])) {
155 for(size_t i3 = 0; i3 < composite_units.size(); i3++) {
156 if(composite_units[i3] == cu) {
157 b = true;
158 break;
159 }
160 }
161 if(!b) composite_units.push_back(cu);
162 do_erase = true;
163 break;
164 }
165 }
166 }
167 if(do_erase) {
168 alias_units.erase(alias_units.begin() + i);
169 for(int i2 = 1; i2 <= (int) cu->countUnits(); i2++) {
170 b = false;
171 Unit *cub = cu->get(i2);
172 switch(cub->subtype()) {
173 case SUBTYPE_BASE_UNIT: {
174 for(size_t i3 = 0; i3 < base_units.size(); i3++) {
175 if(base_units[i3] == cub) {
176 b = true;
177 break;
178 }
179 }
180 if(!b) base_units.push_back(cub);
181 break;
182 }
183 case SUBTYPE_ALIAS_UNIT: {
184 for(size_t i3 = 0; i3 < alias_units.size(); i3++) {
185 if(alias_units[i3] == cub) {
186 b = true;
187 break;
188 }
189 }
190 if(!b) alias_units.push_back((AliasUnit*) cub);
191 break;
192 }
193 case SUBTYPE_COMPOSITE_UNIT: {
194 gatherInformation(((CompositeUnit*) cub)->generateMathStructure(), base_units, alias_units);
195 break;
196 }
197 }
198 }
199 i = 0;
200 } else {
201 i++;
202 }
203 }
204
205 for(size_t i = 0; i < alias_units.size();) {
206 do_erase = false;
207 for(size_t i2 = 0; i2 < alias_units.size(); i2++) {
208 if(i != i2 && alias_units[i]->baseUnit() == alias_units[i2]->baseUnit()) {
209 if(alias_units[i2]->isParentOf(alias_units[i])) {
210 do_erase = true;
211 break;
212 } else if(!alias_units[i]->isParentOf(alias_units[i2])) {
213 b = false;
214 for(size_t i3 = 0; i3 < base_units.size(); i3++) {
215 if(base_units[i3] == alias_units[i2]->firstBaseUnit()) {
216 b = true;
217 break;
218 }
219 }
220 if(!b) base_units.push_back((Unit*) alias_units[i]->baseUnit());
221 do_erase = true;
222 break;
223 }
224 }
225 }
226 if(do_erase) {
227 alias_units.erase(alias_units.begin() + i);
228 i = 0;
229 } else {
230 i++;
231 }
232 }
233 for(size_t i = 0; i < alias_units.size();) {
234 do_erase = false;
235 if(alias_units[i]->baseUnit()->subtype() == SUBTYPE_BASE_UNIT) {
236 for(size_t i2 = 0; i2 < base_units.size(); i2++) {
237 if(alias_units[i]->baseUnit() == base_units[i2]) {
238 do_erase = true;
239 break;
240 }
241 }
242 }
243 if(do_erase) {
244 alias_units.erase(alias_units.begin() + i);
245 i = 0;
246 } else {
247 i++;
248 }
249 }
250 b = false;
251 bool fcr = false;
252 for(size_t i = 0; i < composite_units.size(); i++) {
253 if(convert(composite_units[i], sync_nonlinear_relations, (found_nonlinear_relations || sync_nonlinear_relations) ? &fcr : NULL, calculate_new_functions, feo)) b = true;
254 }
255 if(dissolveAllCompositeUnits()) b = true;
256 for(size_t i = 0; i < base_units.size(); i++) {
257 if(convert(base_units[i], sync_nonlinear_relations, (found_nonlinear_relations || sync_nonlinear_relations) ? &fcr : NULL, calculate_new_functions, feo)) b = true;
258 }
259 for(size_t i = 0; i < alias_units.size(); i++) {
260 if(convert(alias_units[i], sync_nonlinear_relations, (found_nonlinear_relations || sync_nonlinear_relations) ? &fcr : NULL, calculate_new_functions, feo)) b = true;
261 }
262 if(b && sync_nonlinear_relations && fcr) CALCULATOR->error(false, _("Calculations involving conversion of units without proportional linear relationship might give unexpected results and is not recommended."), NULL);
263 if(fcr && found_nonlinear_relations) *found_nonlinear_relations = fcr;
264 return b;
265 }
266
has_approximate_relation_to_base(Unit * u,bool do_intervals)267 bool has_approximate_relation_to_base(Unit *u, bool do_intervals) {
268 if(u->subtype() == SUBTYPE_ALIAS_UNIT) {
269 if(((AliasUnit*) u)->isApproximate()) return do_intervals;
270 if(((AliasUnit*) u)->expression().find_first_not_of(NUMBER_ELEMENTS EXPS) != string::npos && !((AliasUnit*) u)->hasNonlinearExpression()) return true;
271 return has_approximate_relation_to_base(((AliasUnit*) u)->firstBaseUnit());
272 } else if(u->subtype() == SUBTYPE_COMPOSITE_UNIT) {
273 for(size_t i = 1; i <= ((CompositeUnit*) u)->countUnits(); i++) {
274 if(has_approximate_relation_to_base(((CompositeUnit*) u)->get(i))) return true;
275 }
276 }
277 return false;
278 }
279
testDissolveCompositeUnit(Unit * u)280 bool MathStructure::testDissolveCompositeUnit(Unit *u) {
281 if(m_type == STRUCT_UNIT) {
282 if(o_unit->subtype() == SUBTYPE_COMPOSITE_UNIT) {
283 if(((CompositeUnit*) o_unit)->containsRelativeTo(u)) {
284 set(((CompositeUnit*) o_unit)->generateMathStructure());
285 return true;
286 }
287 } else if(o_unit->subtype() == SUBTYPE_ALIAS_UNIT && o_unit->baseUnit()->subtype() == SUBTYPE_COMPOSITE_UNIT) {
288 if(((CompositeUnit*) (o_unit->baseUnit()))->containsRelativeTo(u)) {
289 if(convert(o_unit->baseUnit())) {
290 convert(u);
291 return true;
292 }
293 }
294 }
295 }
296 return false;
297 }
test_dissolve_cu(MathStructure & mstruct,Unit * u,bool convert_nonlinear_relations,bool * found_nonlinear_relations,bool calculate_new_functions,const EvaluationOptions & feo,Prefix * new_prefix=NULL)298 bool test_dissolve_cu(MathStructure &mstruct, Unit *u, bool convert_nonlinear_relations, bool *found_nonlinear_relations, bool calculate_new_functions, const EvaluationOptions &feo, Prefix *new_prefix = NULL) {
299 if(mstruct.isUnit()) {
300 if(mstruct.unit()->subtype() == SUBTYPE_COMPOSITE_UNIT) {
301 if(((CompositeUnit*) mstruct.unit())->containsRelativeTo(u)) {
302 mstruct.set(((CompositeUnit*) mstruct.unit())->generateMathStructure());
303 return true;
304 }
305 } else if(mstruct.unit()->subtype() == SUBTYPE_ALIAS_UNIT && mstruct.unit()->baseUnit()->subtype() == SUBTYPE_COMPOSITE_UNIT) {
306 if(((CompositeUnit*) (mstruct.unit()->baseUnit()))->containsRelativeTo(u)) {
307 if(mstruct.convert(mstruct.unit()->baseUnit(), convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo)) {
308 mstruct.convert(u, convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, new_prefix);
309 return true;
310 }
311 }
312 }
313 }
314 return false;
315 }
testCompositeUnit(Unit * u)316 bool MathStructure::testCompositeUnit(Unit *u) {
317 if(m_type == STRUCT_UNIT) {
318 if(o_unit->subtype() == SUBTYPE_COMPOSITE_UNIT) {
319 if(((CompositeUnit*) o_unit)->containsRelativeTo(u)) {
320 return true;
321 }
322 } else if(o_unit->subtype() == SUBTYPE_ALIAS_UNIT && o_unit->baseUnit()->subtype() == SUBTYPE_COMPOSITE_UNIT) {
323 if(((CompositeUnit*) (o_unit->baseUnit()))->containsRelativeTo(u)) {
324 return true;
325 }
326 }
327 }
328 return false;
329 }
dissolveAllCompositeUnits()330 bool MathStructure::dissolveAllCompositeUnits() {
331 switch(m_type) {
332 case STRUCT_UNIT: {
333 if(o_unit->subtype() == SUBTYPE_COMPOSITE_UNIT) {
334 set(((CompositeUnit*) o_unit)->generateMathStructure());
335 return true;
336 }
337 break;
338 }
339 default: {
340 bool b = false;
341 for(size_t i = 0; i < SIZE; i++) {
342 if(CHILD(i).dissolveAllCompositeUnits()) {
343 CHILD_UPDATED(i);
344 b = true;
345 }
346 }
347 return b;
348 }
349 }
350 return false;
351 }
setPrefixForUnit(Unit * u,Prefix * new_prefix)352 bool MathStructure::setPrefixForUnit(Unit *u, Prefix *new_prefix) {
353 if(m_type == STRUCT_UNIT && o_unit == u) {
354 if(o_prefix != new_prefix) {
355 Number new_value(1, 1);
356 if(o_prefix) new_value = o_prefix->value();
357 if(new_prefix) new_value.divide(new_prefix->value());
358 o_prefix = new_prefix;
359 multiply(new_value);
360 return true;
361 }
362 return false;
363 }
364 bool b = false;
365 for(size_t i = 0; i < SIZE; i++) {
366 if(CHILD(i).setPrefixForUnit(u, new_prefix)) {
367 CHILD_UPDATED(i);
368 b = true;
369 }
370 }
371 return b;
372 }
373
searchSubMultiplicationsForComplexRelations(Unit * u,const MathStructure & mstruct)374 bool searchSubMultiplicationsForComplexRelations(Unit *u, const MathStructure &mstruct) {
375 int b_c = -1;
376 for(size_t i = 0; i < mstruct.size(); i++) {
377 if(mstruct[i].isUnit_exp()) {
378 if((mstruct[i].isUnit() && u->hasNonlinearRelationTo(mstruct[i].unit())) || (mstruct[i].isPower() && u->hasNonlinearRelationTo(mstruct[i][0].unit()))) {
379 return true;
380 }
381 } else if(b_c == -1 && mstruct[i].isMultiplication()) {
382 b_c = -3;
383 }
384 }
385 if(b_c == -3) {
386 for(size_t i = 0; i < mstruct.size(); i++) {
387 if(mstruct[i].isMultiplication() && searchSubMultiplicationsForComplexRelations(u, mstruct[i])) return true;
388 }
389 }
390 return false;
391 }
convertToBaseUnits(bool convert_nonlinear_relations,bool * found_nonlinear_relations,bool calculate_new_functions,const EvaluationOptions & feo,bool avoid_approximate_variables)392 bool MathStructure::convertToBaseUnits(bool convert_nonlinear_relations, bool *found_nonlinear_relations, bool calculate_new_functions, const EvaluationOptions &feo, bool avoid_approximate_variables) {
393 if(m_type == STRUCT_UNIT) {
394 if(o_unit->subtype() == SUBTYPE_COMPOSITE_UNIT) {
395 set(((CompositeUnit*) o_unit)->generateMathStructure());
396 convertToBaseUnits(convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, avoid_approximate_variables);
397 return true;
398 } else if(o_unit->subtype() == SUBTYPE_ALIAS_UNIT) {
399 AliasUnit *au = (AliasUnit*) o_unit;
400 if(au->hasNonlinearRelationTo(au->baseUnit())) {
401 if(found_nonlinear_relations) *found_nonlinear_relations = true;
402 if(!convert_nonlinear_relations) {
403 if(!au->hasNonlinearExpression() && ((feo.approximation != APPROXIMATION_EXACT && feo.approximation != APPROXIMATION_EXACT_VARIABLES) || !au->hasApproximateExpression(avoid_approximate_variables, false))) {
404 MathStructure mstruct_old(*this);
405 if(convert(au->firstBaseUnit(), false, NULL, calculate_new_functions, feo) && !equals(mstruct_old)) {
406 convertToBaseUnits(false, NULL, calculate_new_functions, feo, avoid_approximate_variables);
407 return true;
408 }
409 }
410 return false;
411 }
412 }
413 if((feo.approximation == APPROXIMATION_EXACT || feo.approximation == APPROXIMATION_EXACT_VARIABLES) && au->hasApproximateRelationTo(au->baseUnit(), avoid_approximate_variables, false)) {
414 MathStructure mstruct_old(*this);
415 if(convert(au->firstBaseUnit(), false, NULL, calculate_new_functions, feo) && !equals(mstruct_old)) {
416 convertToBaseUnits(false, NULL, calculate_new_functions, feo, avoid_approximate_variables);
417 return true;
418 }
419 return false;
420 }
421 if(convert(au->baseUnit(), convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo)) {
422 convertToBaseUnits(convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, avoid_approximate_variables);
423 return true;
424 }
425 }
426 return false;
427 } else if(m_type == STRUCT_MULTIPLICATION && (convert_nonlinear_relations || found_nonlinear_relations)) {
428 AliasUnit *complex_au = NULL;
429 if(convert_nonlinear_relations && convertToBaseUnits(false, NULL, calculate_new_functions, feo, avoid_approximate_variables)) {
430 convertToBaseUnits(convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, avoid_approximate_variables);
431 return true;
432 }
433 for(size_t i = 0; i < SIZE; i++) {
434 if(CALCULATOR->aborted()) return false;
435 if(CHILD(i).isUnit_exp() && CHILD(i).unit_exp_unit()->subtype() == SUBTYPE_ALIAS_UNIT) {
436 AliasUnit *au = (AliasUnit*) CHILD(i).unit_exp_unit();
437 if(au && au->hasNonlinearRelationTo(au->baseUnit())) {
438 if(found_nonlinear_relations) {
439 *found_nonlinear_relations = true;
440 }
441 if(convert_nonlinear_relations) {
442 if(complex_au) {
443 complex_au = NULL;
444 convert_nonlinear_relations = false;
445 break;
446 } else {
447 complex_au = au;
448 }
449 } else {
450 break;
451 }
452 }
453 }
454 }
455 if(convert_nonlinear_relations && complex_au && ((feo.approximation != APPROXIMATION_EXACT && feo.approximation != APPROXIMATION_EXACT_VARIABLES) || !complex_au->hasApproximateExpression(avoid_approximate_variables, false))) {
456 MathStructure mstruct_old(*this);
457 if(convert(complex_au->firstBaseUnit(), true, NULL, calculate_new_functions, feo) && !equals(mstruct_old)) {
458 convertToBaseUnits(convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, avoid_approximate_variables);
459 return true;
460 }
461 }
462 } else if(m_type == STRUCT_FUNCTION) {
463 if(o_function->id() == FUNCTION_ID_STRIP_UNITS) return false;
464 bool b = false;
465 for(size_t i = 0; i < SIZE; i++) {
466 if(CALCULATOR->aborted()) return b;
467 if((!o_function->getArgumentDefinition(i + 1) || o_function->getArgumentDefinition(i + 1)->type() != ARGUMENT_TYPE_ANGLE) && CHILD(i).convertToBaseUnits(convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, avoid_approximate_variables)) {
468 CHILD_UPDATED(i);
469 b = true;
470 }
471 }
472 return b;
473 }
474 bool b = false;
475 for(size_t i = 0; i < SIZE; i++) {
476 if(CALCULATOR->aborted()) return b;
477 if(CHILD(i).convertToBaseUnits(convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, avoid_approximate_variables)) {
478 CHILD_UPDATED(i);
479 b = true;
480 }
481 }
482 return b;
483 }
484 bool convert_approximate(MathStructure &m, Unit *u, const EvaluationOptions &feo, vector<KnownVariable*> *vars, vector<MathStructure> *uncs, vector<Unit*> *units, bool do_intervals);
convert_approximate(MathStructure & m,const MathStructure unit_mstruct,const EvaluationOptions & feo,vector<KnownVariable * > * vars,vector<MathStructure> * uncs,vector<Unit * > * units,bool do_intervals)485 bool convert_approximate(MathStructure &m, const MathStructure unit_mstruct, const EvaluationOptions &feo, vector<KnownVariable*> *vars, vector<MathStructure> *uncs, vector<Unit*> *units, bool do_intervals) {
486 bool b = false;
487 if(unit_mstruct.type() == STRUCT_UNIT) {
488 if(convert_approximate(m, unit_mstruct.unit(), feo, vars, uncs, units, do_intervals)) b = true;
489 } else {
490 for(size_t i = 0; i < unit_mstruct.size(); i++) {
491 if(convert_approximate(m, unit_mstruct[i], feo, vars, uncs, units, do_intervals)) b = true;
492 }
493 }
494 return b;
495 }
test_dissolve_cu_approximate(MathStructure & mstruct,Unit * u,const EvaluationOptions & feo,vector<KnownVariable * > * vars,vector<MathStructure> * uncs,vector<Unit * > * units,bool do_intervals)496 bool test_dissolve_cu_approximate(MathStructure &mstruct, Unit *u, const EvaluationOptions &feo, vector<KnownVariable*> *vars, vector<MathStructure> *uncs, vector<Unit*> *units, bool do_intervals) {
497 if(mstruct.isUnit()) {
498 if(mstruct.unit()->subtype() == SUBTYPE_COMPOSITE_UNIT) {
499 if(((CompositeUnit*) mstruct.unit())->containsRelativeTo(u)) {
500 mstruct.set(((CompositeUnit*) mstruct.unit())->generateMathStructure());
501 return true;
502 }
503 } else if(mstruct.unit()->subtype() == SUBTYPE_ALIAS_UNIT && mstruct.unit()->baseUnit()->subtype() == SUBTYPE_COMPOSITE_UNIT) {
504 if(((CompositeUnit*) (mstruct.unit()->baseUnit()))->containsRelativeTo(u)) {
505 if(convert_approximate(mstruct, mstruct.unit()->baseUnit(), feo, vars, uncs, units, do_intervals)) {
506 convert_approximate(mstruct, u, feo, vars, uncs, units, do_intervals);
507 return true;
508 }
509 }
510 }
511 }
512 return false;
513 }
convert_approximate(MathStructure & m,Unit * u,const EvaluationOptions & feo,vector<KnownVariable * > * vars,vector<MathStructure> * uncs,vector<Unit * > * units,bool do_intervals)514 bool convert_approximate(MathStructure &m, Unit *u, const EvaluationOptions &feo, vector<KnownVariable*> *vars, vector<MathStructure> *uncs, vector<Unit*> *units, bool do_intervals) {
515 bool b = false;
516 if(m.type() == STRUCT_UNIT && (m.unit() == u || m.prefix())) {
517 return false;
518 }
519 if(u->subtype() == SUBTYPE_COMPOSITE_UNIT && !(m.type() == STRUCT_UNIT && m.unit()->baseUnit() == u)) {
520 return convert_approximate(m, ((CompositeUnit*) u)->generateMathStructure(false, true), feo, vars, uncs, units, do_intervals);
521 }
522 if(m.type() == STRUCT_UNIT) {
523 if(u->hasApproximateRelationTo(m.unit(), feo.approximation != APPROXIMATION_EXACT && feo.approximation != APPROXIMATION_EXACT_VARIABLES, true) || u->hasNonlinearRelationTo(m.unit())) {
524 return false;
525 }
526 if(!vars) return true;
527 if(m.unit()->baseUnit() != u->baseUnit() && test_dissolve_cu_approximate(m, u, feo, vars, uncs, units, do_intervals)) {
528 convert_approximate(m, u, feo, vars, uncs, units, do_intervals);
529 return true;
530 }
531 MathStructure *exp = new MathStructure(1, 1, 0);
532 MathStructure *mstruct = new MathStructure(1, 1, 0);
533 Unit *u_m = m.unit();
534 if(u_m->subtype() == SUBTYPE_ALIAS_UNIT && do_intervals) {
535 for(size_t i = 0; i < units->size(); i++) {
536 if((*units)[i] == u_m) {
537 mstruct->set((*vars)[i]);
538 u_m = ((AliasUnit*) u_m)->firstBaseUnit();
539 }
540 }
541 if(u_m == m.unit()) {
542 ((AliasUnit*) u_m)->convertToFirstBaseUnit(*mstruct, *exp);
543 if(mstruct->isNumber() && mstruct->number().isInterval()) {
544 uncs->push_back(mstruct->number().uncertainty());
545 units->push_back(u_m);
546 Number nmid(mstruct->number());
547 nmid.intervalToMidValue();
548 nmid.setApproximate(false);
549 KnownVariable *v = new KnownVariable("", string("(") + format_and_print(nmid) + ")", nmid);
550 mstruct->set(v);
551 vars->push_back(v);
552 v->destroy();
553 u_m = ((AliasUnit*) u_m)->firstBaseUnit();
554 } else {
555 mstruct->set(1, 1, 0);
556 exp->set(1, 1, 0);
557 }
558 }
559 }
560 if(u->convert(u_m, *mstruct, *exp) && (do_intervals || (!mstruct->containsInterval(true, false, false, 1, true) && !exp->containsInterval(true, false, false, 1, true)))) {
561 m.setUnit(u);
562 if(!exp->isOne()) {
563 if(feo.calculate_functions) {
564 calculate_nondifferentiable_functions(*exp, feo, true, true, feo.interval_calculation != INTERVAL_CALCULATION_VARIANCE_FORMULA ? 0 : ((feo.approximation != APPROXIMATION_EXACT && feo.approximation != APPROXIMATION_EXACT_VARIABLES) ? 2 : 1));
565 }
566 if(do_intervals) exp->calculatesub(feo, feo, true);
567 m.raise_nocopy(exp);
568 } else {
569 exp->unref();
570 }
571 if(!mstruct->isOne()) {
572 if(feo.calculate_functions) {
573 calculate_nondifferentiable_functions(*mstruct, feo, true, true, feo.interval_calculation != INTERVAL_CALCULATION_VARIANCE_FORMULA ? 0 : ((feo.approximation != APPROXIMATION_EXACT && feo.approximation != APPROXIMATION_EXACT_VARIABLES) ? 2 : 1));
574 }
575 if(do_intervals) mstruct->calculatesub(feo, feo, true);
576 m.multiply_nocopy(mstruct);
577 } else {
578 mstruct->unref();
579 }
580 return true;
581 } else {
582 exp->unref();
583 mstruct->unref();
584 return false;
585 }
586 } else {
587 if(m.type() == STRUCT_FUNCTION) {
588 if(m.function()->id() == FUNCTION_ID_STRIP_UNITS) return b;
589 for(size_t i = 0; i < m.size(); i++) {
590 if(m.size() > 100 && CALCULATOR->aborted()) return b;
591 if((!m.function()->getArgumentDefinition(i + 1) || m.function()->getArgumentDefinition(i + 1)->type() != ARGUMENT_TYPE_ANGLE) && convert_approximate(m[i], u, feo, vars, uncs, units, do_intervals)) {
592 m.childUpdated(i + 1);
593 b = true;
594 }
595 }
596 return b;
597 }
598 for(size_t i = 0; i < m.size(); i++) {
599 if(m.size() > 100 && CALCULATOR->aborted()) return b;
600 if(convert_approximate(m[i], u, feo, vars, uncs, units, do_intervals)) {
601 m.childUpdated(i + 1);
602 b = true;
603 }
604 }
605 return b;
606 }
607 return b;
608 }
609
contains_approximate_relation_to_base(const MathStructure & m,bool do_intervals)610 bool contains_approximate_relation_to_base(const MathStructure &m, bool do_intervals) {
611 if(m.isUnit()) {
612 return has_approximate_relation_to_base(m.unit(), do_intervals);
613 } else if(m.isFunction() && m.function()->id() == FUNCTION_ID_STRIP_UNITS) {
614 return false;
615 }
616 for(size_t i = 0; i < m.size(); i++) {
617 if(contains_approximate_relation_to_base(m[i], do_intervals)) return true;
618 }
619 return false;
620 }
621
sync_approximate_units(MathStructure & m,const EvaluationOptions & feo,vector<KnownVariable * > * vars,vector<MathStructure> * uncs,bool do_intervals)622 bool sync_approximate_units(MathStructure &m, const EvaluationOptions &feo, vector<KnownVariable*> *vars, vector<MathStructure> *uncs, bool do_intervals) {
623 if(m.size() == 0) return false;
624 if(!contains_approximate_relation_to_base(m, do_intervals)) return false;
625 bool check_variables = (feo.approximation != APPROXIMATION_EXACT && feo.approximation != APPROXIMATION_EXACT_VARIABLES);
626 vector<Unit*> base_units;
627 vector<AliasUnit*> alias_units;
628 vector<CompositeUnit*> composite_units;
629 gatherInformation(m, base_units, alias_units, check_variables);
630 if(alias_units.empty() || base_units.size() + alias_units.size() == 1) return false;
631 CompositeUnit *cu;
632 bool b = false, do_erase = false;
633 for(size_t i = 0; i < alias_units.size(); ) {
634 do_erase = false;
635 if(alias_units[i]->baseUnit()->subtype() == SUBTYPE_COMPOSITE_UNIT) {
636 b = false;
637 cu = (CompositeUnit*) alias_units[i]->baseUnit();
638 for(size_t i2 = 0; i2 < base_units.size(); i2++) {
639 if(cu->containsRelativeTo(base_units[i2])) {
640 for(size_t i3 = 0; i3 < composite_units.size(); i3++) {
641 if(composite_units[i3] == cu) {
642 b = true;
643 break;
644 }
645 }
646 if(!b) composite_units.push_back(cu);
647 do_erase = true;
648 break;
649 }
650 }
651 for(size_t i2 = 0; !do_erase && i2 < alias_units.size(); i2++) {
652 if(i != i2 && alias_units[i2]->baseUnit() != cu && cu->containsRelativeTo(alias_units[i2])) {
653 for(size_t i3 = 0; i3 < composite_units.size(); i3++) {
654 if(composite_units[i3] == cu) {
655 b = true;
656 break;
657 }
658 }
659 if(!b) composite_units.push_back(cu);
660 do_erase = true;
661 break;
662 }
663 }
664 }
665 if(do_erase) {
666 alias_units.erase(alias_units.begin() + i);
667 for(int i2 = 1; i2 <= (int) cu->countUnits(); i2++) {
668 b = false;
669 Unit *cub = cu->get(i2);
670 switch(cub->subtype()) {
671 case SUBTYPE_BASE_UNIT: {
672 for(size_t i3 = 0; i3 < base_units.size(); i3++) {
673 if(base_units[i3] == cub) {
674 b = true;
675 break;
676 }
677 }
678 if(!b) base_units.push_back(cub);
679 break;
680 }
681 case SUBTYPE_ALIAS_UNIT: {
682 for(size_t i3 = 0; i3 < alias_units.size(); i3++) {
683 if(alias_units[i3] == cub) {
684 b = true;
685 break;
686 }
687 }
688 if(!b) alias_units.push_back((AliasUnit*) cub);
689 break;
690 }
691 case SUBTYPE_COMPOSITE_UNIT: {
692 gatherInformation(((CompositeUnit*) cub)->generateMathStructure(), base_units, alias_units, check_variables);
693 break;
694 }
695 }
696 }
697 i = 0;
698 } else {
699 i++;
700 }
701 }
702
703 for(size_t i = 0; i < alias_units.size();) {
704 do_erase = false;
705 for(size_t i2 = 0; i2 < alias_units.size(); i2++) {
706 if(i != i2 && alias_units[i]->baseUnit() == alias_units[i2]->baseUnit()) {
707 if(alias_units[i2]->isParentOf(alias_units[i])) {
708 do_erase = true;
709 break;
710 } else if(!alias_units[i]->isParentOf(alias_units[i2])) {
711 b = false;
712 for(size_t i3 = 0; i3 < base_units.size(); i3++) {
713 if(base_units[i3] == alias_units[i2]->firstBaseUnit()) {
714 b = true;
715 break;
716 }
717 }
718 if(!b) base_units.push_back((Unit*) alias_units[i]->baseUnit());
719 do_erase = true;
720 break;
721 }
722 }
723 }
724 if(do_erase) {
725 alias_units.erase(alias_units.begin() + i);
726 i = 0;
727 } else {
728 i++;
729 }
730 }
731 for(size_t i = 0; i < alias_units.size();) {
732 do_erase = false;
733 if(alias_units[i]->baseUnit()->subtype() == SUBTYPE_BASE_UNIT) {
734 for(size_t i2 = 0; i2 < base_units.size(); i2++) {
735 if(alias_units[i]->baseUnit() == base_units[i2]) {
736 do_erase = true;
737 break;
738 }
739 }
740 }
741 if(do_erase) {
742 alias_units.erase(alias_units.begin() + i);
743 i = 0;
744 } else {
745 i++;
746 }
747 }
748 b = false;
749 vector<Unit*> units;
750 for(size_t i = 0; i < composite_units.size(); i++) {
751 if(convert_approximate(m, composite_units[i], feo, vars, uncs, &units, do_intervals)) b = true;
752 }
753 if(m.dissolveAllCompositeUnits()) b = true;
754 for(size_t i = 0; i < base_units.size(); i++) {
755 if(convert_approximate(m, base_units[i], feo, vars, uncs, &units, do_intervals)) b = true;
756 }
757 for(size_t i = 0; i < alias_units.size(); i++) {
758 if(convert_approximate(m, alias_units[i], feo, vars, uncs, &units, do_intervals)) b = true;
759 }
760 return b;
761 }
762
763
convert(Unit * u,bool convert_nonlinear_relations,bool * found_nonlinear_relations,bool calculate_new_functions,const EvaluationOptions & feo,Prefix * new_prefix)764 bool MathStructure::convert(Unit *u, bool convert_nonlinear_relations, bool *found_nonlinear_relations, bool calculate_new_functions, const EvaluationOptions &feo, Prefix *new_prefix) {
765 if(m_type == STRUCT_ADDITION && containsType(STRUCT_DATETIME, false, true, false) > 0) return false;
766 bool b = false;
767 if(m_type == STRUCT_UNIT && o_unit == u) {
768 if((new_prefix || o_prefix) && o_prefix != new_prefix) {
769 Number new_value(1, 1);
770 if(o_prefix) new_value = o_prefix->value();
771 if(new_prefix) new_value.divide(new_prefix->value());
772 o_prefix = new_prefix;
773 multiply(new_value);
774 return true;
775 }
776 return false;
777 }
778 if(u->subtype() == SUBTYPE_COMPOSITE_UNIT && !(m_type == STRUCT_UNIT && o_unit->baseUnit() == u)) {
779 return convert(((CompositeUnit*) u)->generateMathStructure(false, true), convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo);
780 }
781 if(m_type == STRUCT_UNIT) {
782 if(u->hasNonlinearRelationTo(o_unit)) {
783 if(found_nonlinear_relations) *found_nonlinear_relations = true;
784 if(!convert_nonlinear_relations) return false;
785 }
786 if(o_unit->baseUnit() != u->baseUnit() && test_dissolve_cu(*this, u, convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, new_prefix)) {
787 convert(u, convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, new_prefix);
788 return true;
789 }
790 MathStructure *exp = new MathStructure(1, 1, 0);
791 MathStructure *mstruct = new MathStructure(1, 1, 0);
792 if(o_prefix) {
793 mstruct->set(o_prefix->value());
794 }
795 if(u->convert(o_unit, *mstruct, *exp) && (feo.approximation != APPROXIMATION_EXACT || (!mstruct->isApproximate() && !exp->isApproximate()))) {
796 setUnit(u);
797 o_prefix = new_prefix;
798 if(new_prefix) {
799 divide(new_prefix->value());
800 }
801 if(!exp->isOne()) {
802 if(calculate_new_functions) exp->calculateFunctions(feo, true, false);
803 raise_nocopy(exp);
804 } else {
805 exp->unref();
806 }
807 if(!mstruct->isOne()) {
808 if(calculate_new_functions) mstruct->calculateFunctions(feo, true, false);
809 multiply_nocopy(mstruct);
810 } else {
811 mstruct->unref();
812 }
813 return true;
814 } else {
815 exp->unref();
816 mstruct->unref();
817 return false;
818 }
819 } else {
820 if(convert_nonlinear_relations || found_nonlinear_relations) {
821 if(m_type == STRUCT_MULTIPLICATION) {
822 long int b_c = -1;
823 for(size_t i = 0; i < SIZE; i++) {
824 if(CHILD(i).isUnit_exp()) {
825 Unit *u2 = CHILD(i).isPower() ? CHILD(i)[0].unit() : CHILD(i).unit();
826 if(u->hasNonlinearRelationTo(u2)) {
827 if(found_nonlinear_relations) *found_nonlinear_relations = true;
828
829 b_c = i;
830 break;
831 }
832 } else if(CHILD(i).isMultiplication() && (CALCULATOR->getTemperatureCalculationMode() == TEMPERATURE_CALCULATION_RELATIVE || u->baseUnit() != CALCULATOR->getUnitById(UNIT_ID_KELVIN))) {
833 b_c = -3;
834 }
835 }
836 if(b_c == -3) {
837 for(size_t i = 0; i < SIZE; i++) {
838 if(CHILD(i).isMultiplication()) {
839 if(searchSubMultiplicationsForComplexRelations(u, CHILD(i))) {
840 if(!convert_nonlinear_relations) {
841 *found_nonlinear_relations = true;
842 break;
843 }
844 flattenMultiplication(*this);
845 return convert(u, convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, new_prefix);
846 }
847 }
848 }
849 }
850 if(convert_nonlinear_relations && b_c >= 0) {
851 if((CALCULATOR->getTemperatureCalculationMode() == TEMPERATURE_CALCULATION_RELATIVE || u->baseUnit() != CALCULATOR->getUnitById(UNIT_ID_KELVIN)) && flattenMultiplication(*this)) return convert(u, convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, new_prefix);
852 MathStructure mstruct(1, 1);
853 MathStructure mstruct2(1, 1);
854 if(SIZE == 2) {
855 if(b_c == 0) mstruct = CHILD(1);
856 else mstruct = CHILD(0);
857 if(mstruct.containsType(STRUCT_UNIT, false, true, true) > 0) {
858 mstruct2 = mstruct;
859 mstruct.set(1, 1, 0);
860 }
861 } else if(SIZE > 2) {
862 mstruct = *this;
863 size_t nr_of_del = 0;
864 for(size_t i = 0; i < SIZE; i++) {
865 if(CHILD(i).containsType(STRUCT_UNIT, false, true, true) > 0) {
866 mstruct.delChild(i + 1 - nr_of_del);
867 nr_of_del++;
868 if((long int) i != b_c) {
869 if(mstruct2.isOne()) mstruct2 = CHILD(i);
870 else mstruct2.multiply(CHILD(i), true);
871 }
872 }
873 }
874 if(mstruct.size() == 1) mstruct.setToChild(1);
875 else if(mstruct.size() == 0) mstruct.set(1, 1, 0);
876 }
877 MathStructure exp(1, 1);
878 Unit *u2;
879 bool b_p = false;
880 if(CHILD(b_c).isPower()) {
881 if(CHILD(b_c)[0].unit()->baseUnit() != u->baseUnit()) {
882 if(CHILD(b_c)[0].unit()->subtype() != SUBTYPE_BASE_UNIT && (CHILD(b_c)[0].unit()->subtype() != SUBTYPE_ALIAS_UNIT || ((AliasUnit*) CHILD(b_c)[0].unit())->firstBaseUnit()->subtype() != SUBTYPE_COMPOSITE_UNIT)) {
883 convertToBaseUnits(convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo);
884 } else {
885 return false;
886 }
887 convert(u, convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, new_prefix);
888 return true;
889 }
890 exp = CHILD(b_c)[1];
891 u2 = CHILD(b_c)[0].unit();
892 if(CHILD(b_c)[0].prefix() && CHILD(b_c)[0].prefix() != CALCULATOR->getDecimalNullPrefix() && CHILD(b_c)[0].prefix() != CALCULATOR->getBinaryNullPrefix()) b_p = true;
893 } else {
894 if(CHILD(b_c).unit()->baseUnit() != u->baseUnit()) {
895 if(CHILD(b_c).unit()->subtype() != SUBTYPE_BASE_UNIT && (CHILD(b_c).unit()->subtype() != SUBTYPE_ALIAS_UNIT || ((AliasUnit*) CHILD(b_c).unit())->firstBaseUnit()->subtype() != SUBTYPE_COMPOSITE_UNIT)) {
896 convertToBaseUnits(convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo);
897 } else {
898 return false;
899 }
900 convert(u, convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, new_prefix);
901 return true;
902 }
903 u2 = CHILD(b_c).unit();
904 if(CHILD(b_c).prefix() && CHILD(b_c).prefix() != CALCULATOR->getDecimalNullPrefix() && CHILD(b_c).prefix() != CALCULATOR->getBinaryNullPrefix()) b_p = true;
905 }
906 size_t efc = 0, mfc = 0;
907 if(calculate_new_functions) {
908 efc = exp.countFunctions();
909 mfc = mstruct.countFunctions();
910 }
911 Unit *u1 = u;
912 if((!mstruct2.isOne() || !exp.isOne()) && (CALCULATOR->getTemperatureCalculationMode() == TEMPERATURE_CALCULATION_RELATIVE && u->baseUnit() == CALCULATOR->getUnitById(UNIT_ID_KELVIN))) {
913 if(u2 == CALCULATOR->getUnitById(UNIT_ID_CELSIUS)) u2 = CALCULATOR->getUnitById(UNIT_ID_KELVIN);
914 else if(u2 == CALCULATOR->getUnitById(UNIT_ID_FAHRENHEIT) && CALCULATOR->getUnitById(UNIT_ID_RANKINE)) u2 = CALCULATOR->getUnitById(UNIT_ID_RANKINE);
915 if(u1 == CALCULATOR->getUnitById(UNIT_ID_CELSIUS)) u1 = CALCULATOR->getUnitById(UNIT_ID_KELVIN);
916 else if(u1 == CALCULATOR->getUnitById(UNIT_ID_FAHRENHEIT) && CALCULATOR->getUnitById(UNIT_ID_RANKINE)) u1 = CALCULATOR->getUnitById(UNIT_ID_RANKINE);
917 }
918 if(u1->convert(u2, mstruct, exp)) {
919 if(feo.approximation == APPROXIMATION_EXACT && !isApproximate() && (mstruct.isApproximate() || exp.isApproximate())) return false;
920 if(b_p) {
921 EvaluationOptions eo = feo;
922 eo.keep_prefixes = false;
923 unformat(eo);
924 return convert(u, convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, new_prefix);
925 }
926 set(u);
927 if(!exp.isOne()) {
928 if(calculate_new_functions && exp.countFunctions() > efc) exp.calculateFunctions(feo, true, false);
929 raise(exp);
930 }
931 if(!mstruct2.isOne()) {
932 multiply(mstruct2);
933 }
934 if(!mstruct.isOne()) {
935 if(calculate_new_functions && mstruct.countFunctions() > mfc) mstruct.calculateFunctions(feo, true, false);
936 multiply(mstruct);
937 }
938 if(u->baseUnit() != CALCULATOR->getUnitById(UNIT_ID_KELVIN)) convert(u, convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, new_prefix);
939 return true;
940 }
941 return false;
942 }
943 } else if(m_type == STRUCT_POWER) {
944 if(CHILD(0).isUnit() && u->hasNonlinearRelationTo(CHILD(0).unit())) {
945 if(found_nonlinear_relations) *found_nonlinear_relations = true;
946 if(convert_nonlinear_relations) {
947 if(CHILD(0).unit()->baseUnit() != u->baseUnit()) {
948 if(CHILD(0).unit()->subtype() != SUBTYPE_BASE_UNIT && (CHILD(0).unit()->subtype() != SUBTYPE_ALIAS_UNIT || ((AliasUnit*) CHILD(0).unit())->firstBaseUnit()->subtype() != SUBTYPE_COMPOSITE_UNIT)) {
949 convertToBaseUnits(convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo);
950 } else {
951 return false;
952 }
953 convert(u, convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, new_prefix);
954 return true;
955 }
956 MathStructure exp(CHILD(1));
957 MathStructure mstruct(1, 1);
958 if(CHILD(0).prefix()) {
959 mstruct.set(CHILD(0).prefix()->value());
960 mstruct.raise(exp);
961 }
962 size_t efc = 0;
963 if(calculate_new_functions) {
964 efc = exp.countFunctions();
965 }
966 if(u->convert(CHILD(0).unit(), mstruct, exp)) {
967 if(feo.approximation == APPROXIMATION_EXACT && !isApproximate() && (mstruct.isApproximate() || exp.isApproximate())) return false;
968 set(u);
969 if(!exp.isOne()) {
970 if(calculate_new_functions && exp.countFunctions() > efc) exp.calculateFunctions(feo, true, false);
971 raise(exp);
972 }
973 if(!mstruct.isOne()) {
974 if(calculate_new_functions) mstruct.calculateFunctions(feo, true, false);
975 multiply(mstruct);
976 }
977 return true;
978 }
979 return false;
980 }
981 }
982 }
983 }
984 if(m_type == STRUCT_FUNCTION) {
985 if(o_function->id() == FUNCTION_ID_STRIP_UNITS) return b;
986 for(size_t i = 0; i < SIZE; i++) {
987 if(CALCULATOR->aborted()) return b;
988 if((!o_function->getArgumentDefinition(i + 1) || o_function->getArgumentDefinition(i + 1)->type() != ARGUMENT_TYPE_ANGLE) && CHILD(i).convert(u, convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, new_prefix)) {
989 CHILD_UPDATED(i);
990 b = true;
991 }
992 }
993 return b;
994 }
995 for(size_t i = 0; i < SIZE; i++) {
996 if(CALCULATOR->aborted()) return b;
997 if(CHILD(i).convert(u, convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, new_prefix)) {
998 CHILD_UPDATED(i);
999 b = true;
1000 }
1001 }
1002 return b;
1003 }
1004 return b;
1005 }
convert(const MathStructure unit_mstruct,bool convert_nonlinear_relations,bool * found_nonlinear_relations,bool calculate_new_functions,const EvaluationOptions & feo)1006 bool MathStructure::convert(const MathStructure unit_mstruct, bool convert_nonlinear_relations, bool *found_nonlinear_relations, bool calculate_new_functions, const EvaluationOptions &feo) {
1007 bool b = false;
1008 if(unit_mstruct.type() == STRUCT_UNIT) {
1009 if(convert(unit_mstruct.unit(), convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, feo.keep_prefixes ? unit_mstruct.prefix() : NULL)) b = true;
1010 } else {
1011 for(size_t i = 0; i < unit_mstruct.size(); i++) {
1012 if(convert(unit_mstruct[i], convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo)) b = true;
1013 }
1014 }
1015 return b;
1016 }
1017
1018