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
23 #include <map>
24 #include <algorithm>
25
26 #include "MathStructure-support.h"
27
28 using std::string;
29 using std::cout;
30 using std::vector;
31 using std::ostream;
32 using std::endl;
33
printRecursive(const MathStructure & mstruct)34 void printRecursive(const MathStructure &mstruct) {
35 std::cout << "RECURSIVE " << mstruct.print() << std::endl;
36 for(size_t i = 0; i < mstruct.size(); i++) {
37 std::cout << i << ": " << mstruct[i].print() << std::endl;
38 for(size_t i2 = 0; i2 < mstruct[i].size(); i2++) {
39 std::cout << i << "-" << i2 << ": " << mstruct[i][i2].print() << std::endl;
40 for(size_t i3 = 0; i3 < mstruct[i][i2].size(); i3++) {
41 std::cout << i << "-" << i2 << "-" << i3 << ": " << mstruct[i][i2][i3].print() << std::endl;
42 for(size_t i4 = 0; i4 < mstruct[i][i2][i3].size(); i4++) {
43 std::cout << i << "-" << i2 << "-" << i3 << "-" << i4 << ": " << mstruct[i][i2][i3][i4].print() << std::endl;
44 for(size_t i5 = 0; i5 < mstruct[i][i2][i3][i4].size(); i5++) {
45 std::cout << i << "-" << i2 << "-" << i3 << "-" << i4 << "-" << i5 << ": " << mstruct[i][i2][i3][i4][i5].print() << std::endl;
46 for(size_t i6 = 0; i6 < mstruct[i][i2][i3][i4][i5].size(); i6++) {
47 std::cout << i << "-" << i2 << "-" << i3 << "-" << i4 << "-" << i5 << "-" << i6 << ": " << mstruct[i][i2][i3][i4][i5][i6].print() << std::endl;
48 for(size_t i7 = 0; i7 < mstruct[i][i2][i3][i4][i5][i6].size(); i7++) {
49 std::cout << i << "-" << i2 << "-" << i3 << "-" << i4 << "-" << i5 << "-" << i6 << "-" << i7 << ": " << mstruct[i][i2][i3][i4][i5][i6][i7].print() << std::endl;
50 for(size_t i8 = 0; i8 < mstruct[i][i2][i3][i4][i5][i6][i7].size(); i8++) {
51 std::cout << i << "-" << i2 << "-" << i3 << "-" << i4 << "-" << i5 << "-" << i6 << "-" << i7 << "-" << i8 << ": " << mstruct[i][i2][i3][i4][i5][i6][i7][i8].print() << std::endl;
52 for(size_t i9 = 0; i9 < mstruct[i][i2][i3][i4][i5][i6][i7][i8].size(); i9++) {
53 std::cout << i << "-" << i2 << "-" << i3 << "-" << i4 << "-" << i5 << "-" << i6 << "-" << i7 << "-" << i8 << "-" << i9 << ": " << mstruct[i][i2][i3][i4][i5][i6][i7][i8][i9].print() << std::endl;
54 }
55 }
56 }
57 }
58 }
59 }
60 }
61 }
62 }
63 }
64
format_and_print(const MathStructure & mstruct)65 string format_and_print(const MathStructure &mstruct) {
66 MathStructure m_print(mstruct);
67 if(CALCULATOR) {
68 m_print.sort(CALCULATOR->messagePrintOptions());
69 m_print.formatsub(CALCULATOR->messagePrintOptions(), NULL, 0, true, &m_print);
70 return m_print.print(CALCULATOR->messagePrintOptions());
71 } else {
72 PrintOptions po;
73 po.interval_display = INTERVAL_DISPLAY_PLUSMINUS;
74 po.spell_out_logical_operators = true;
75 po.number_fraction_format = FRACTION_FRACTIONAL;
76 m_print.sort(po);
77 m_print.formatsub(po, NULL, 0, true, &m_print);
78 return m_print.print(po);
79 }
80 }
81
name_is_less(const string & str1,const string & str2)82 bool name_is_less(const string &str1, const string &str2) {
83 for(size_t i = 0; ; i++) {
84 if(i == str1.length()) return true;
85 if(i == str2.length()) return false;
86 char c1 = str1[i];
87 char c2 = str2[i];
88 if(c1 < 0 || c2 < 0) break;
89 if(c1 >= 'A' && c1 <= 'Z') c1 += 'a' - 'A';
90 if(c2 >= 'A' && c2 <= 'Z') c2 += 'a' - 'A';
91 if(c1 < c2) return true;
92 if(c1 > c2) return false;
93 }
94 char *s1 = utf8_strdown(str1.c_str());
95 char *s2 = utf8_strdown(str2.c_str());
96 if(s1 && s2) {
97 bool b = strcmp(s1, s2) < 0;
98 free(s1);
99 free(s2);
100 return b;
101 }
102 return false;
103 }
104
105 int sortCompare(const MathStructure &mstruct1, const MathStructure &mstruct2, const MathStructure &parent, const PrintOptions &po);
sortCompare(const MathStructure & mstruct1,const MathStructure & mstruct2,const MathStructure & parent,const PrintOptions & po)106 int sortCompare(const MathStructure &mstruct1, const MathStructure &mstruct2, const MathStructure &parent, const PrintOptions &po) {
107 // returns -1 if mstruct1 should be placed before mstruct2, 1 if mstruct1 should be placed after mstruct2, and 0 if current order should be preserved
108 if(parent.isMultiplication()) {
109 if(!mstruct1.representsNonMatrix() && !mstruct2.representsNonMatrix()) {
110 // the order of matrices should be preserved
111 return 0;
112 }
113 if(mstruct1.isNumber() && mstruct2.isPower() && mstruct2[0].isInteger() && mstruct2[1].isInteger() && mstruct2[1].representsPositive()) {
114 return sortCompare(mstruct1, mstruct2[0], parent, po);
115 }
116 if(mstruct2.isNumber() && mstruct1.isPower() && mstruct1[0].isInteger() && mstruct1[1].isInteger() && mstruct1[1].representsPositive()) {
117 return sortCompare(mstruct1[0], mstruct2, parent, po);
118 }
119 if(mstruct1.isPower() && mstruct2.isPower() && mstruct1[0].isInteger() && mstruct1[1].isInteger() && mstruct1[1].representsPositive() && mstruct2[0].isInteger() && mstruct2[1].isInteger() && mstruct2[1].representsPositive()) {
120 return sortCompare(mstruct1[0], mstruct2[0], parent, po);
121 }
122 }
123 if(parent.isAddition()) {
124
125 // always place constant of definite integral last
126 if(mstruct1.isVariable() && mstruct1.variable() == CALCULATOR->getVariableById(VARIABLE_ID_C)) return 1;
127 if(mstruct2.isVariable() && mstruct2.variable() == CALCULATOR->getVariableById(VARIABLE_ID_C)) return -1;
128
129 if(po.sort_options.minus_last) {
130 // -a+b=b-a
131 bool m1 = mstruct1.hasNegativeSign(), m2 = mstruct2.hasNegativeSign();
132 if(m1 && !m2) {
133 return 1;
134 } else if(m2 && !m1) {
135 return -1;
136 }
137 }
138
139 if((mstruct1.isUnit() || (mstruct1.isMultiplication() && mstruct1.size() == 2 && mstruct1[1].isUnit())) && (mstruct2.isUnit() || (mstruct2.isMultiplication() && mstruct2.size() == 2 && mstruct2[1].isUnit()))) {
140 Unit *u1, *u2;
141 if(mstruct1.isUnit()) u1 = mstruct1.unit();
142 else u1 = mstruct1[1].unit();
143 if(mstruct2.isUnit()) u2 = mstruct2.unit();
144 else u2 = mstruct2[1].unit();
145 if(u1->isParentOf(u2)) return 1;
146 if(u2->isParentOf(u1)) return -1;
147 }
148 }
149 bool isdiv1 = false, isdiv2 = false;
150 if(!po.negative_exponents || !mstruct1.isUnit_exp() || !mstruct2.isUnit_exp()) {
151 // determine if mstruct1 and/or mstruct2 is division (a*b^-1)
152 if(mstruct1.isMultiplication()) {
153 for(size_t i = 0; i < mstruct1.size(); i++) {
154 if(mstruct1[i].isPower() && mstruct1[i][1].hasNegativeSign()) {
155 isdiv1 = true;
156 break;
157 }
158 }
159 } else if(mstruct1.isPower() && mstruct1[1].hasNegativeSign()) {
160 isdiv1 = true;
161 }
162 if(mstruct2.isMultiplication()) {
163 for(size_t i = 0; i < mstruct2.size(); i++) {
164 if(mstruct2[i].isPower() && mstruct2[i][1].hasNegativeSign()) {
165 isdiv2 = true;
166 break;
167 }
168 }
169 } else if(mstruct2.isPower() && mstruct2[1].hasNegativeSign()) {
170 isdiv2 = true;
171 }
172 }
173 if(parent.isAddition() && isdiv1 == isdiv2) {
174 // sort using single factors from left to right
175 if(mstruct1.isMultiplication() && mstruct1.size() > 0) {
176 size_t start = 0;
177 while(mstruct1[start].isNumber() && mstruct1.size() > start + 1) {
178 start++;
179 }
180 int i2;
181 if(mstruct2.isMultiplication()) {
182 if(mstruct2.size() < 1) return -1;
183 size_t start2 = 0;
184 while(mstruct2[start2].isNumber() && mstruct2.size() > start2 + 1) {
185 start2++;
186 }
187 for(size_t i = 0; i + start < mstruct1.size(); i++) {
188 if(i + start2 >= mstruct2.size()) return 1;
189 i2 = sortCompare(mstruct1[i + start], mstruct2[i + start2], parent, po);
190 if(i2 != 0) return i2;
191 }
192 if(mstruct1.size() - start == mstruct2.size() - start2) return 0;
193 if(parent.isMultiplication()) return -1;
194 else return 1;
195 } else {
196 i2 = sortCompare(mstruct1[start], mstruct2, parent, po);
197 if(i2 != 0) return i2;
198 }
199 } else if(mstruct2.isMultiplication() && mstruct2.size() > 0) {
200 size_t start = 0;
201 while(mstruct2[start].isNumber() && mstruct2.size() > start + 1) {
202 start++;
203 }
204 int i2;
205 if(mstruct1.isMultiplication()) {
206 return 1;
207 } else {
208 i2 = sortCompare(mstruct1, mstruct2[start], parent, po);
209 if(i2 != 0) return i2;
210 }
211 }
212 }
213 if(mstruct1.type() != mstruct2.type()) {
214 if(mstruct1.isVariable() && mstruct2.isSymbolic()) {
215 if(parent.isMultiplication()) {
216 // place constant (known) factors first (before symbols)
217 if(mstruct1.variable()->isKnown()) return -1;
218 }
219 // sort variables and symbols in alphabetical order
220 if(name_is_less(mstruct1.variable()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg).name, mstruct2.symbol())) return -1;
221 else return 1;
222 }
223 if(mstruct2.isVariable() && mstruct1.isSymbolic()) {
224 if(parent.isMultiplication()) {
225 // place constant (known) factors first (before symbols)
226 if(mstruct2.variable()->isKnown()) return 1;
227 }
228 // sort variables and symbols in alphabetical order
229 if(name_is_less(mstruct1.symbol(), mstruct2.variable()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg).name)) return -1;
230 else return 1;
231 }
232 if(!parent.isMultiplication() || (!mstruct1.isNumber() && !mstruct2.isNumber())) {
233 // sort exponentiation with non-exponentiation (has exponent 1), excluding number factors
234 if(mstruct2.isPower()) {
235 if(mstruct2[0].isUnit() && mstruct1.isUnit()) return -1;
236 int i = sortCompare(mstruct1, mstruct2[0], parent, po);
237 if(i == 0) {
238 return sortCompare(m_one, mstruct2[1], parent, po);
239 }
240 return i;
241 }
242 if(mstruct1.isPower()) {
243 if(mstruct1[0].isUnit() && mstruct2.isUnit()) return 1;
244 int i = sortCompare(mstruct1[0], mstruct2, parent, po);
245 if(i == 0) {
246 return sortCompare(mstruct1[1], m_one, parent, po);
247 }
248 return i;
249 }
250 }
251 if(parent.isMultiplication()) {
252 // place unit factors last
253 if(mstruct2.isUnit()) return -1;
254 if(mstruct1.isUnit()) return 1;
255 if(mstruct1.isAddition() && !mstruct2.isAddition() && !mstruct1.containsUnknowns() && (mstruct2.isUnknown_exp() || (mstruct2.isMultiplication() && mstruct2.containsUnknowns()))) return -1;
256 if(mstruct2.isAddition() && !mstruct1.isAddition() && !mstruct2.containsUnknowns() && (mstruct1.isUnknown_exp() || (mstruct1.isMultiplication() && mstruct1.containsUnknowns()))) return 1;
257 }
258 // types listed in sort order (aborted is placed last)
259 if(mstruct2.isAborted()) return -1;
260 if(mstruct1.isAborted()) return 1;
261 if(mstruct2.isInverse()) return -1;
262 if(mstruct1.isInverse()) return 1;
263 if(mstruct2.isDivision()) return -1;
264 if(mstruct1.isDivision()) return 1;
265 if(mstruct2.isNegate()) return -1;
266 if(mstruct1.isNegate()) return 1;
267 if(mstruct2.isLogicalAnd()) return -1;
268 if(mstruct1.isLogicalAnd()) return 1;
269 if(mstruct2.isLogicalOr()) return -1;
270 if(mstruct1.isLogicalOr()) return 1;
271 if(mstruct2.isLogicalXor()) return -1;
272 if(mstruct1.isLogicalXor()) return 1;
273 if(mstruct2.isLogicalNot()) return -1;
274 if(mstruct1.isLogicalNot()) return 1;
275 if(mstruct2.isComparison()) return -1;
276 if(mstruct1.isComparison()) return 1;
277 if(mstruct2.isBitwiseOr()) return -1;
278 if(mstruct1.isBitwiseOr()) return 1;
279 if(mstruct2.isBitwiseXor()) return -1;
280 if(mstruct1.isBitwiseXor()) return 1;
281 if(mstruct2.isBitwiseAnd()) return -1;
282 if(mstruct1.isBitwiseAnd()) return 1;
283 if(mstruct2.isBitwiseNot()) return -1;
284 if(mstruct1.isBitwiseNot()) return 1;
285 if(mstruct2.isUndefined()) return -1;
286 if(mstruct1.isUndefined()) return 1;
287 if(mstruct2.isFunction()) return -1;
288 if(mstruct1.isFunction()) return 1;
289 if(mstruct2.isAddition()) return -1;
290 if(mstruct1.isAddition()) return 1;
291 if(!parent.isMultiplication()) {
292 // place division last
293 if(isdiv2 && mstruct2.isMultiplication()) return -1;
294 if(isdiv1 && mstruct1.isMultiplication()) return 1;
295 // place number after multiplication, exponentiation, unit, symbol, variable and date/time
296 if(mstruct2.isNumber()) return -1;
297 if(mstruct1.isNumber()) return 1;
298 }
299 if(mstruct2.isMultiplication()) return -1;
300 if(mstruct1.isMultiplication()) return 1;
301 if(mstruct2.isPower()) return -1;
302 if(mstruct1.isPower()) return 1;
303 if(mstruct2.isUnit()) return -1;
304 if(mstruct1.isUnit()) return 1;
305 if(mstruct2.isSymbolic()) return -1;
306 if(mstruct1.isSymbolic()) return 1;
307 if(mstruct2.isVariable()) return -1;
308 if(mstruct1.isVariable()) return 1;
309 if(mstruct2.isDateTime()) return -1;
310 if(mstruct1.isDateTime()) return 1;
311 if(parent.isMultiplication()) {
312 // only reached when type of 1 or 2 is a vector (place number factor after vector)
313 if(mstruct2.isNumber()) return -1;
314 if(mstruct1.isNumber()) return 1;
315 }
316 return -1;
317 }
318 switch(mstruct1.type()) {
319 case STRUCT_NUMBER: {
320 bool inc_order = parent.isMultiplication();
321 if(!mstruct1.number().hasImaginaryPart() && !mstruct2.number().hasImaginaryPart()) {
322 // real numbers
323 ComparisonResult cmp;
324 // if the numbers are factors with different signs, place smallest number first (the one with the negative sign)
325 if(parent.isMultiplication() && mstruct2.number().isNegative() != mstruct1.number().isNegative()) cmp = mstruct2.number().compare(mstruct1.number());
326 // otherwise, place largest number first
327 else cmp = mstruct1.number().compare(mstruct2.number());
328 if(cmp == COMPARISON_RESULT_LESS) return inc_order ? 1 : -1;
329 else if(cmp == COMPARISON_RESULT_GREATER) return inc_order ? -1 : 1;
330 return 0;
331 } else {
332 if(!mstruct1.number().hasRealPart()) {
333 if(mstruct2.number().hasRealPart()) {
334 // place number with real part before number without
335 return 1;
336 } else {
337 // compare imaginary parts
338 ComparisonResult cmp = mstruct1.number().compareImaginaryParts(mstruct2.number());
339 if(cmp == COMPARISON_RESULT_LESS) return inc_order ? 1 : -1;
340 else if(cmp == COMPARISON_RESULT_GREATER) return inc_order ? -1 : 1;
341 return 0;
342 }
343 } else if(mstruct2.number().hasRealPart()) {
344 // compare real parts first
345 ComparisonResult cmp = mstruct1.number().compareRealParts(mstruct2.number());
346 if(cmp == COMPARISON_RESULT_EQUAL) {
347 // if real parts are equal, compare imaginary parts
348 cmp = mstruct1.number().compareImaginaryParts(mstruct2.number());
349 }
350 if(cmp == COMPARISON_RESULT_LESS) return inc_order ? 1 : -1;
351 else if(cmp == COMPARISON_RESULT_GREATER) return inc_order ? -1 : 1;
352 return 0;
353 } else {
354 return -1;
355 }
356 }
357 return -1;
358 }
359 case STRUCT_UNIT: {
360 bool p1 = mstruct1.prefix() && mstruct1.prefix() != CALCULATOR->getDecimalNullPrefix() && mstruct1.prefix() != CALCULATOR->getBinaryNullPrefix();
361 bool p2 = mstruct2.prefix() && mstruct2.prefix() != CALCULATOR->getDecimalNullPrefix() && mstruct2.prefix() != CALCULATOR->getBinaryNullPrefix();
362 if(p1 && !p2) return -1;
363 if(p2 && !p1) return 1;
364 if(mstruct1.unit() == mstruct2.unit()) return 0;
365 p1 = mstruct1.unit()->useWithPrefixesByDefault() || (po.use_prefixes_for_currencies && mstruct1.unit()->isCurrency());
366 p2 = mstruct2.unit()->useWithPrefixesByDefault() || (po.use_prefixes_for_currencies && mstruct2.unit()->isCurrency());
367 if(p1 && !p2) return -1;
368 if(p2 && !p1) return 1;
369 // sort units in alphabetical order
370 if(name_is_less(mstruct1.unit()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, mstruct1.isPlural(), po.use_reference_names).name, mstruct2.unit()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, mstruct2.isPlural(), po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg).name)) return -1;
371 return 1;
372 }
373 case STRUCT_SYMBOLIC: {
374 // sort symbols in alphabetical order
375 if(mstruct1.symbol() < mstruct2.symbol()) return -1;
376 else if(mstruct1.symbol() == mstruct2.symbol()) return 0;
377 return 1;
378 }
379 case STRUCT_VARIABLE: {
380 if(mstruct1.variable() == mstruct2.variable()) return 0;
381 if(parent.isMultiplication()) {
382 // place constant (known) factors first (before unknown variables)
383 if(mstruct1.variable()->isKnown() && !mstruct2.variable()->isKnown()) return -1;
384 if(!mstruct1.variable()->isKnown() && mstruct2.variable()->isKnown()) return 1;
385 }
386 // sort variables in alphabetical order
387 if(name_is_less(mstruct1.variable()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names).name, mstruct2.variable()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg).name)) return -1;
388 return 1;
389 }
390 case STRUCT_FUNCTION: {
391 if(mstruct1.function() == mstruct2.function()) {
392 for(size_t i = 0; i < mstruct2.size(); i++) {
393 if(i >= mstruct1.size()) {
394 // place function with less arguments first (if common arguments are equal)
395 return -1;
396 }
397 // sort same functions using arguments
398 int i2 = sortCompare(mstruct1[i], mstruct2[i], parent, po);
399 if(i2 != 0) return i2;
400 }
401 return 0;
402 }
403 // sort functions in alphabetical order
404 if(name_is_less(mstruct1.function()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names).name, mstruct2.function()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg).name)) return -1;
405 return 1;
406 }
407 case STRUCT_POWER: {
408 if(parent.isMultiplication() && mstruct1[0].isUnit() && mstruct2[0].isUnit()) {
409 int i = sortCompare(mstruct1[1], mstruct2[1], parent, po);
410 if(i == 0) {
411 return sortCompare(mstruct1[0], mstruct2[0], parent, po);
412 }
413 return i;
414 }
415 // compare bases first
416 int i = sortCompare(mstruct1[0], mstruct2[0], parent, po);
417 if(i == 0) {
418 // compare exponents if bases are equal
419 return sortCompare(mstruct1[1], mstruct2[1], parent, po);
420 }
421 return i;
422 }
423 case STRUCT_MULTIPLICATION: {
424 if(isdiv1 != isdiv2) {
425 // place denominator last
426 if(isdiv1) return 1;
427 return -1;
428 }
429 }
430 case STRUCT_COMPARISON: {
431 if(mstruct1.comparisonType() != mstruct2.comparisonType()) {
432 // place equality before inequality, place greater before less
433 if(mstruct2.comparisonType() == COMPARISON_EQUALS || ((mstruct1.comparisonType() == COMPARISON_LESS || mstruct1.comparisonType() == COMPARISON_EQUALS_LESS) && (mstruct2.comparisonType() == COMPARISON_GREATER || mstruct2.comparisonType() == COMPARISON_EQUALS_GREATER))) {
434 return 1;
435 }
436 if(mstruct1.comparisonType() == COMPARISON_EQUALS || ((mstruct1.comparisonType() == COMPARISON_GREATER || mstruct1.comparisonType() == COMPARISON_EQUALS_GREATER) && (mstruct2.comparisonType() == COMPARISON_LESS || mstruct2.comparisonType() == COMPARISON_EQUALS_LESS))) {
437 return -1;
438 }
439 }
440 }
441 default: {
442 int ie;
443 for(size_t i = 0; i < mstruct1.size(); i++) {
444 // place MathStructure with less children first (if common children are equal)
445 if(i >= mstruct2.size()) return 1;
446 // sort by comparing children
447 ie = sortCompare(mstruct1[i], mstruct2[i], parent, po);
448 if(ie != 0) {
449 return ie;
450 }
451 }
452 }
453 }
454 return 0;
455 }
456
sort(const PrintOptions & po,bool recursive)457 void MathStructure::sort(const PrintOptions &po, bool recursive) {
458 // sort before output
459 if(recursive) {
460 for(size_t i = 0; i < SIZE; i++) {
461 if(CALCULATOR->aborted()) break;
462 CHILD(i).sort(po);
463 }
464 }
465 if(m_type == STRUCT_COMPARISON) {
466 // place zero and numbers last in comparison
467 if((CHILD(0).isZero() && !CHILD(1).isZero()) || (CHILD(0).isNumber() && !CHILD(1).isNumber())) {
468 SWAP_CHILDREN(0, 1)
469 if(ct_comp == COMPARISON_LESS) ct_comp = COMPARISON_GREATER;
470 else if(ct_comp == COMPARISON_EQUALS_LESS) ct_comp = COMPARISON_EQUALS_GREATER;
471 else if(ct_comp == COMPARISON_GREATER) ct_comp = COMPARISON_LESS;
472 else if(ct_comp == COMPARISON_EQUALS_GREATER) ct_comp = COMPARISON_EQUALS_LESS;
473 }
474 return;
475 }
476 // only sort addition, multiplication, bitwise AND, OR, XOR, and logical AND, OR
477 if(m_type != STRUCT_ADDITION && m_type != STRUCT_MULTIPLICATION && m_type != STRUCT_BITWISE_AND && m_type != STRUCT_BITWISE_OR && m_type != STRUCT_BITWISE_XOR && m_type != STRUCT_LOGICAL_AND && m_type != STRUCT_LOGICAL_OR) return;
478 // do not sort addition containing date/time
479 if(m_type == STRUCT_ADDITION && containsType(STRUCT_DATETIME, false, true, false) > 0) return;
480 vector<size_t> sorted;
481 bool b;
482 PrintOptions po2 = po;
483 po2.sort_options.minus_last = po.sort_options.minus_last && SIZE == 2;
484 for(size_t i = 0; i < SIZE; i++) {
485 if(CALCULATOR->aborted()) return;
486 b = false;
487 for(size_t i2 = 0; i2 < sorted.size(); i2++) {
488 if(sortCompare(CHILD(i), *v_subs[sorted[i2]], *this, po2) < 0) {
489 sorted.insert(sorted.begin() + i2, v_order[i]);
490 b = true;
491 break;
492 }
493 }
494 if(!b) sorted.push_back(v_order[i]);
495 }
496 if(CALCULATOR->aborted()) return;
497 if(m_type == STRUCT_ADDITION && SIZE > 2 && po.sort_options.minus_last && v_subs[sorted[0]]->hasNegativeSign()) {
498 for(size_t i2 = 1; i2 < sorted.size(); i2++) {
499 if(CALCULATOR->aborted()) return;
500 if(!v_subs[sorted[i2]]->hasNegativeSign()) {
501 sorted.insert(sorted.begin(), sorted[i2]);
502 sorted.erase(sorted.begin() + (i2 + 1));
503 break;
504 }
505 }
506 }
507 if(CALCULATOR->aborted()) return;
508 for(size_t i2 = 0; i2 < sorted.size(); i2++) {
509 v_order[i2] = sorted[i2];
510 }
511 }
512
unformat(const EvaluationOptions & eo)513 void MathStructure::unformat(const EvaluationOptions &eo) {
514 if(m_type == STRUCT_FUNCTION && o_function->id() == FUNCTION_ID_STRIP_UNITS) {
515 EvaluationOptions eo2 = eo;
516 eo2.keep_prefixes = true;
517 for(size_t i = 0; i < SIZE; i++) {
518 CHILD(i).unformat(eo2);
519 }
520 } else {
521 for(size_t i = 0; i < SIZE; i++) {
522 CHILD(i).unformat(eo);
523 }
524 }
525 switch(m_type) {
526 case STRUCT_INVERSE: {
527 APPEND(m_minus_one);
528 m_type = STRUCT_POWER;
529 break;
530 }
531 case STRUCT_NEGATE: {
532 PREPEND(m_minus_one);
533 m_type = STRUCT_MULTIPLICATION;
534 break;
535 }
536 case STRUCT_DIVISION: {
537 CHILD(1).raise(m_minus_one);
538 m_type = STRUCT_MULTIPLICATION;
539 break;
540 }
541 case STRUCT_UNIT: {
542 if(o_prefix && !eo.keep_prefixes) {
543 if(o_prefix == CALCULATOR->getDecimalNullPrefix() || o_prefix == CALCULATOR->getBinaryNullPrefix()) {
544 o_prefix = NULL;
545 } else {
546 Unit *u = o_unit;
547 Prefix *p = o_prefix;
548 set(p->value());
549 multiply(u);
550 }
551 unformat(eo);
552 break;
553 } else if(o_unit->subtype() == SUBTYPE_COMPOSITE_UNIT) {
554 set(((CompositeUnit*) o_unit)->generateMathStructure(false, eo.keep_prefixes));
555 unformat(eo);
556 break;
557 }
558 b_plural = false;
559 break;
560 }
561 default: {}
562 }
563 }
564
idm1(const MathStructure & mnum,bool & bfrac,bool & bint)565 void idm1(const MathStructure &mnum, bool &bfrac, bool &bint) {
566 switch(mnum.type()) {
567 case STRUCT_NUMBER: {
568 if((!bfrac || bint) && mnum.number().isRational()) {
569 if(!mnum.number().isInteger()) {
570 bint = false;
571 bfrac = true;
572 }
573 } else {
574 bint = false;
575 }
576 break;
577 }
578 case STRUCT_MULTIPLICATION: {
579 if((!bfrac || bint) && mnum.size() > 0 && mnum[0].isNumber() && mnum[0].number().isRational()) {
580 if(!mnum[0].number().isInteger()) {
581 bint = false;
582 bfrac = true;
583 }
584
585 } else {
586 bint = false;
587 }
588 break;
589 }
590 case STRUCT_ADDITION: {
591 bool b_a = false;
592 for(size_t i = 0; i < mnum.size() && (!bfrac || bint); i++) {
593 if(mnum[i].isAddition()) b_a = true;
594 else idm1(mnum[i], bfrac, bint);
595 }
596 if(b_a) bint = false;
597 break;
598 }
599 default: {
600 bint = false;
601 }
602 }
603 }
idm2(const MathStructure & mnum,bool & bfrac,bool & bint,Number & nr)604 void idm2(const MathStructure &mnum, bool &bfrac, bool &bint, Number &nr) {
605 switch(mnum.type()) {
606 case STRUCT_NUMBER: {
607 if(mnum.number().isRational()) {
608 if(mnum.number().isInteger()) {
609 if(bint) {
610 if(mnum.number().isOne()) {
611 bint = false;
612 } else if(nr.isOne()) {
613 nr = mnum.number();
614 } else if(nr != mnum.number()) {
615 nr.gcd(mnum.number());
616 if(nr.isOne()) bint = false;
617 }
618 }
619 } else {
620 if(nr.isOne()) {
621 nr = mnum.number().denominator();
622 } else {
623 Number nden(mnum.number().denominator());
624 if(nr != nden) {
625 Number ngcd(nden);
626 ngcd.gcd(nr);
627 nden /= ngcd;
628 nr *= nden;
629 }
630 }
631 }
632 }
633 break;
634 }
635 case STRUCT_MULTIPLICATION: {
636 if(mnum.size() > 0 && mnum[0].isNumber() && mnum[0].number().isRational()) {
637 if(mnum[0].number().isInteger()) {
638 if(bint) {
639 if(mnum[0].number().isOne()) {
640 bint = false;
641 } else if(nr.isOne()) {
642 nr = mnum[0].number();
643 } else if(nr != mnum[0].number()) {
644 nr.gcd(mnum[0].number());
645 if(nr.isOne()) bint = false;
646 }
647 }
648 } else {
649 if(nr.isOne()) {
650 nr = mnum[0].number().denominator();
651 } else {
652 Number nden(mnum[0].number().denominator());
653 if(nr != nden) {
654 Number ngcd(nden);
655 ngcd.gcd(nr);
656 nden /= ngcd;
657 nr *= nden;
658 }
659 }
660 }
661 }
662 break;
663 }
664 case STRUCT_ADDITION: {
665 for(size_t i = 0; i < mnum.size() && (bfrac || bint); i++) {
666 if(!mnum[i].isAddition()) idm2(mnum[i], bfrac, bint, nr);
667 }
668 break;
669 }
670 default: {}
671 }
672 }
idm3(MathStructure & mnum,Number & nr,bool expand)673 int idm3(MathStructure &mnum, Number &nr, bool expand) {
674 switch(mnum.type()) {
675 case STRUCT_NUMBER: {
676 mnum.number() *= nr;
677 mnum.numberUpdated();
678 break;
679 }
680 case STRUCT_MULTIPLICATION: {
681 if(mnum.size() > 0 && mnum[0].isNumber()) {
682 mnum[0].number() *= nr;
683 if(mnum[0].number().isOne() && mnum.size() != 1) {
684 mnum.delChild(1, true);
685 }
686 return -1;
687 } else if(expand) {
688 for(size_t i = 0; i < mnum.size(); i++) {
689 if(mnum[i].isAddition()) {
690 idm3(mnum[i], nr, true);
691 return -1;
692 }
693 }
694 }
695 mnum.insertChild(nr, 1);
696 return 1;
697 }
698 case STRUCT_ADDITION: {
699 if(expand) {
700 for(size_t i = 0; i < mnum.size(); i++) {
701 idm3(mnum[i], nr, true);
702 }
703 break;
704 }
705 }
706 default: {
707 mnum.transform(STRUCT_MULTIPLICATION);
708 mnum.insertChild(nr, 1);
709 return -1;
710 }
711 }
712 return 0;
713 }
714
idm1b(const MathStructure & mnum,bool & bint,bool & bint2)715 void idm1b(const MathStructure &mnum, bool &bint, bool &bint2) {
716 switch(mnum.type()) {
717 case STRUCT_NUMBER: {
718 if(mnum.number().isInteger() && !mnum.number().isOne()) {
719 bint = true;
720 if(mnum.number() > 9 || mnum.number() < -9) bint2 = true;
721 } else {
722 bint = false;
723 }
724 break;
725 }
726 case STRUCT_MULTIPLICATION: {
727 if(mnum.size() > 0 && mnum[0].isNumber()) {
728 idm1b(mnum[0], bint, bint2);
729 } else {
730 bint = false;
731 }
732 break;
733 }
734 case STRUCT_ADDITION: {
735 for(size_t i = 0; i < mnum.size(); i++) {
736 if(mnum[i].isAddition()) bint = false;
737 else idm1b(mnum[i], bint, bint2);
738 if(!bint) break;
739 }
740 break;
741 }
742 default: {
743 bint = false;
744 }
745 }
746 }
idm2b(const MathStructure & mnum,Number & nr)747 void idm2b(const MathStructure &mnum, Number &nr) {
748 switch(mnum.type()) {
749 case STRUCT_NUMBER: {
750 if(nr.isZero() || mnum.number() < nr) nr = mnum.number();
751 break;
752 }
753 case STRUCT_MULTIPLICATION: {
754 idm2b(mnum[0], nr);
755 break;
756 }
757 case STRUCT_ADDITION: {
758 for(size_t i = 0; i < mnum.size(); i++) {
759 idm2b(mnum[i], nr);
760 }
761 break;
762 }
763 default: {}
764 }
765 }
idm3b(MathStructure & mnum,Number & nr)766 void idm3b(MathStructure &mnum, Number &nr) {
767 switch(mnum.type()) {
768 case STRUCT_NUMBER: {
769 mnum.number() /= nr;
770 break;
771 }
772 case STRUCT_MULTIPLICATION: {
773 idm3b(mnum[0], nr);
774 break;
775 }
776 case STRUCT_ADDITION: {
777 for(size_t i = 0; i < mnum.size(); i++) {
778 idm3b(mnum[i], nr);
779 }
780 break;
781 }
782 default: {}
783 }
784 }
785
displays_number_exact(Number nr,const PrintOptions & po,MathStructure * top_parent)786 bool displays_number_exact(Number nr, const PrintOptions &po, MathStructure *top_parent) {
787 if(po.base == BASE_ROMAN_NUMERALS || po.base == BASE_BIJECTIVE_26) return true;
788 InternalPrintStruct ips_n;
789 if(top_parent && top_parent->isApproximate()) ips_n.parent_approximate = true;
790 if(po.show_ending_zeroes && po.restrict_to_parent_precision && ips_n.parent_approximate && (nr > 9 || nr < -9)) return false;
791 if(top_parent && top_parent->precision() < 0) ips_n.parent_precision = top_parent->precision();
792 bool approximately_displayed = false;
793 PrintOptions po2 = po;
794 po2.indicate_infinite_series = false;
795 po2.is_approximate = &approximately_displayed;
796 nr.print(po2, ips_n);
797 return !approximately_displayed;
798 }
799
fix_approximate_multiplier(MathStructure & m,const PrintOptions & po,MathStructure * top_parent=NULL)800 bool fix_approximate_multiplier(MathStructure &m, const PrintOptions &po, MathStructure *top_parent = NULL) {
801 if(!top_parent) top_parent = &m;
802 if(po.number_fraction_format == FRACTION_DECIMAL) {
803 PrintOptions po2 = po;
804 po2.number_fraction_format = FRACTION_FRACTIONAL;
805 po2.restrict_fraction_length = true;
806 return fix_approximate_multiplier(m, po2, top_parent);
807 }
808 bool b_ret = false;
809 if(m.isMultiplication() && m.size() >= 2 && m[0].isNumber() && m[0].number().isRational()) {
810 for(size_t i = 1; i < m.size(); i++) {
811 if(m[i].isAddition()) {
812 bool mul_exact = displays_number_exact(m[0].number(), po, top_parent);
813 bool b = false;
814 for(size_t i2 = 0; i2 < m[i].size() && !b; i2++) {
815 if(m[i][i2].isNumber() && (!mul_exact || !displays_number_exact(m[i][i2].number(), po, top_parent))) {
816 b = true;
817 } else if(m[i][i2].isMultiplication() && m[i][i2].size() >= 2 && m[i][i2][0].isNumber() && (!mul_exact || !displays_number_exact(m[i][i2][0].number(), po, top_parent))) {
818 b = true;
819 }
820 }
821 if(b) {
822 for(size_t i2 = 0; i2 < m[i].size(); i2++) {
823 if(m[i][i2].isNumber()) {
824 if(!m[i][i2].number().multiply(m[0].number())) {
825 m[i][i2].multiply(m[0]);
826 }
827 } else if(m[i][i2].isMultiplication()) {
828 if(m[i][i2].size() < 1 || !m[i][i2][0].isNumber() || !m[i][i2][0].number().multiply(m[0].number())) {
829 m[i][i2].insertChild(m[0], 1);
830 }
831 } else {
832 m[i][i2].multiply(m[0]);
833 m[i][i2].swapChildren(1, 2);
834 }
835 }
836 m.delChild(1, true);
837 b_ret = true;
838 break;
839 }
840 }
841 }
842 }
843 for(size_t i = 0; i < m.size(); i++) {
844 if(fix_approximate_multiplier(m[i], po, top_parent)) {
845 m.childUpdated(i + 1);
846 b_ret = true;
847 }
848 }
849 return b_ret;
850 }
851
idm3_test(bool & b_fail,const MathStructure & mnum,const Number & nr,bool expand,const PrintOptions & po,MathStructure * top_parent)852 int idm3_test(bool &b_fail, const MathStructure &mnum, const Number &nr, bool expand, const PrintOptions &po, MathStructure *top_parent) {
853 switch(mnum.type()) {
854 case STRUCT_NUMBER: {
855 Number nr2(mnum.number());
856 nr2 *= nr;
857 b_fail = !displays_number_exact(nr2, po, top_parent);
858 break;
859 }
860 case STRUCT_MULTIPLICATION: {
861 if(mnum.size() > 0 && mnum[0].isNumber()) {
862 Number nr2(mnum[0].number());
863 nr2 *= nr;
864 b_fail = !nr2.isOne() && !displays_number_exact(nr2, po, top_parent);
865 return -1;
866 } else if(expand) {
867 for(size_t i = 0; i < mnum.size(); i++) {
868 if(mnum[i].isAddition()) {
869 idm3_test(b_fail, mnum[i], nr, true, po, top_parent);
870 return -1;
871 }
872 }
873 }
874 b_fail = !displays_number_exact(nr, po, top_parent);
875 return 1;
876 }
877 case STRUCT_ADDITION: {
878 if(expand) {
879 for(size_t i = 0; i < mnum.size(); i++) {
880 idm3_test(b_fail, mnum[i], nr, true, po, top_parent);
881 if(b_fail) break;
882 }
883 break;
884 }
885 }
886 default: {
887 b_fail = !displays_number_exact(nr, po, top_parent);
888 return -1;
889 }
890 }
891 return 0;
892 }
893
is_unit_multiexp(const MathStructure & mstruct)894 bool is_unit_multiexp(const MathStructure &mstruct) {
895 if(mstruct.isUnit_exp()) return true;
896 if(mstruct.isMultiplication()) {
897 for(size_t i3 = 0; i3 < mstruct.size(); i3++) {
898 if(!mstruct[i3].isUnit_exp()) {
899 return false;
900 break;
901 }
902 }
903 return true;
904 } else if(mstruct.isDivision()) {
905 return is_unit_multiexp(mstruct[0]) && is_unit_multiexp(mstruct[1]);
906 } else if(mstruct.isInverse()) {
907 return is_unit_multiexp(mstruct[0]);
908 }
909 if(mstruct.isPower() && mstruct[0].isMultiplication()) {
910 for(size_t i3 = 0; i3 < mstruct[0].size(); i3++) {
911 if(!mstruct[0][i3].isUnit_exp()) {
912 return false;
913 break;
914 }
915 }
916 return true;
917 }
918 return false;
919 }
920
improve_division_multipliers(const PrintOptions & po,MathStructure * top_parent)921 bool MathStructure::improve_division_multipliers(const PrintOptions &po, MathStructure *top_parent) {
922 if(!top_parent) top_parent = this;
923 switch(m_type) {
924 case STRUCT_MULTIPLICATION: {
925 size_t inum = 0, iden = 0;
926 bool bfrac = false, bint = true, bdiv = false, bnonunitdiv = false;
927 size_t index1 = 0, index2 = 0;
928 bool dofrac = true;
929 for(size_t i2 = 0; i2 < SIZE; i2++) {
930 if(CHILD(i2).isPower() && CHILD(i2)[1].isMinusOne()) {
931 if(!po.place_units_separately || !is_unit_multiexp(CHILD(i2)[0])) {
932 if(iden == 0) index1 = i2;
933 iden++;
934 bdiv = true;
935 if(!CHILD(i2)[0].isUnit()) bnonunitdiv = true;
936 if(CHILD(i2)[0].containsType(STRUCT_ADDITION)) {
937 dofrac = true;
938 }
939 }
940 } else if(!bdiv && CHILD(i2).isPower() && CHILD(i2)[1].hasNegativeSign()) {
941 if(!po.place_units_separately || !is_unit_multiexp(CHILD(i2)[0])) {
942 if(!bdiv) index1 = i2;
943 bdiv = true;
944 if(!CHILD(i2)[0].isUnit()) bnonunitdiv = true;
945 }
946 } else {
947 if(!po.place_units_separately || !is_unit_multiexp(CHILD(i2))) {
948 if(inum == 0) index2 = i2;
949 inum++;
950 }
951 }
952 }
953 if(!bdiv || !bnonunitdiv) break;
954 if(iden > 1) {
955 size_t i2 = index1 + 1;
956 while(i2 < SIZE) {
957 if(CHILD(i2).isPower() && CHILD(i2)[1].isMinusOne()) {
958 CHILD(index1)[0].multiply(CHILD(i2)[0], true);
959 ERASE(i2);
960 if(index2 > i2) index2--;
961 } else {
962 i2++;
963 }
964 }
965 iden = 1;
966 }
967 if(bint) bint = inum > 0 && iden == 1;
968 if(inum > 0) idm1(CHILD(index2), bfrac, bint);
969 if(iden > 0) idm1(CHILD(index1)[0], bfrac, bint);
970 bool b = false;
971 if(!dofrac) bfrac = false;
972 if(bint || bfrac) {
973 Number nr(1, 1);
974 if(inum > 0) idm2(CHILD(index2), bfrac, bint, nr);
975 if(iden > 0) idm2(CHILD(index1)[0], bfrac, bint, nr);
976 if((bint || bfrac) && !nr.isOne()) {
977 if(bint) nr.recip();
978
979 bool b_fail = false;
980 if(inum > 1 && !CHILD(index2).isNumber()) {
981 int i = idm3_test(b_fail, *this, nr, !po.allow_factorization, po, top_parent);
982 if(i >= 0 && !b_fail && iden > 0) idm3_test(b_fail, CHILD(index1)[0], nr, !po.allow_factorization, po, top_parent);
983 } else {
984 if(inum != 0) idm3_test(b_fail, CHILD(index2), nr, !po.allow_factorization, po, top_parent);
985 if(!b_fail && iden > 0) idm3_test(b_fail, CHILD(index1)[0], nr, !po.allow_factorization, po, top_parent);
986 }
987 if(!b_fail) {
988 if(inum == 0) {
989 PREPEND(MathStructure(nr));
990 index1 += 1;
991 } else if(inum > 1 && !CHILD(index2).isNumber()) {
992 int i = idm3(*this, nr, !po.allow_factorization);
993 if(i == 1) index1++;
994 else if(i < 0) iden = 0;
995 } else {
996 idm3(CHILD(index2), nr, !po.allow_factorization);
997 }
998 if(iden > 0) {
999 idm3(CHILD(index1)[0], nr, !po.allow_factorization);
1000 } else {
1001 MathStructure mstruct(nr);
1002 mstruct.raise(m_minus_one);
1003 insertChild(mstruct, index1);
1004 }
1005 b = true;
1006 }
1007 }
1008 }
1009 if(!b && po.show_ending_zeroes && po.restrict_to_parent_precision && top_parent->isApproximate() && po.base != BASE_ROMAN_NUMERALS && po.base != BASE_BIJECTIVE_26 && inum > 0 && iden > 0) {
1010 bint = false;
1011 bool bint2 = false;
1012 idm1b(CHILD(index2), bint, bint2);
1013 if(bint) idm1b(CHILD(index1)[0], bint, bint2);
1014 if(bint && bint2) {
1015 Number nr;
1016 idm2b(CHILD(index2), nr);
1017 idm2b(CHILD(index1)[0], nr);
1018 idm3b(CHILD(index2), nr);
1019 idm3b(CHILD(index1)[0], nr);
1020 }
1021 }
1022 return b;
1023 }
1024 case STRUCT_DIVISION: {
1025 bool bint = true, bfrac = false;
1026 idm1(CHILD(0), bfrac, bint);
1027 idm1(CHILD(1), bfrac, bint);
1028 if(bint || bfrac) {
1029 Number nr(1, 1);
1030 idm2(CHILD(0), bfrac, bint, nr);
1031 idm2(CHILD(1), bfrac, bint, nr);
1032 if((bint || bfrac) && !nr.isOne()) {
1033 if(bint) nr.recip();
1034
1035 bool b_fail = false;
1036 idm3_test(b_fail, CHILD(0), nr, !po.allow_factorization, po, top_parent);
1037 if(b_fail) return false;
1038 idm3_test(b_fail, CHILD(1), nr, !po.allow_factorization, po, top_parent);
1039 if(b_fail) return false;
1040
1041 idm3(CHILD(0), nr, !po.allow_factorization);
1042 idm3(CHILD(1), nr, !po.allow_factorization);
1043 return true;
1044 }
1045 }
1046 break;
1047 }
1048 case STRUCT_INVERSE: {
1049 bool bint = false, bfrac = false;
1050 idm1(CHILD(0), bfrac, bint);
1051 if(bint || bfrac) {
1052 Number nr(1, 1);
1053 idm2(CHILD(0), bfrac, bint, nr);
1054 if((bint || bfrac) && !nr.isOne()) {
1055 bool b_fail = false;
1056 idm3_test(b_fail, CHILD(0), nr, !po.allow_factorization, po, top_parent);
1057 if(b_fail) return false;
1058
1059 setToChild(1, true);
1060 idm3(*this, nr, !po.allow_factorization);
1061 transform_nocopy(STRUCT_DIVISION, new MathStructure(nr));
1062 SWAP_CHILDREN(0, 1);
1063 return true;
1064 }
1065 }
1066 break;
1067 }
1068 case STRUCT_POWER: {
1069 if(CHILD(1).isMinusOne()) {
1070 bool bint = false, bfrac = false;
1071 idm1(CHILD(0), bfrac, bint);
1072 if(bint || bfrac) {
1073 Number nr(1, 1);
1074 idm2(CHILD(0), bfrac, bint, nr);
1075 if((bint || bfrac) && !nr.isOne()) {
1076 bool b_fail = false;
1077 idm3_test(b_fail, CHILD(0), nr, !po.allow_factorization, po, top_parent);
1078 if(b_fail) return false;
1079
1080 idm3(CHILD(0), nr, !po.allow_factorization);
1081 transform(STRUCT_MULTIPLICATION);
1082 PREPEND(MathStructure(nr));
1083 return true;
1084 }
1085 }
1086 break;
1087 }
1088 }
1089 default: {
1090 bool b = false;
1091 for(size_t i = 0; i < SIZE; i++) {
1092 if(CALCULATOR->aborted()) break;
1093 if(CHILD(i).improve_division_multipliers(po, top_parent)) b = true;
1094 }
1095 return b;
1096 }
1097 }
1098 return false;
1099 }
1100
use_prefix_with_unit(Unit * u,const PrintOptions & po)1101 bool use_prefix_with_unit(Unit *u, const PrintOptions &po) {
1102 if(!po.prefix && !po.use_unit_prefixes) {return u->referenceName() == "g" || u->referenceName() == "a";}
1103 if(po.prefix) return true;
1104 if(u->isCurrency()) return po.use_prefixes_for_currencies;
1105 if(po.use_prefixes_for_all_units) return true;
1106 return u->useWithPrefixesByDefault();
1107 }
use_prefix_with_unit(const MathStructure & mstruct,const PrintOptions & po)1108 bool use_prefix_with_unit(const MathStructure &mstruct, const PrintOptions &po) {
1109 if(mstruct.isUnit()) return use_prefix_with_unit(mstruct.unit(), po);
1110 if(mstruct.isUnit_exp()) return use_prefix_with_unit(mstruct[0].unit(), po);
1111 return false;
1112 }
1113
has_prefix(const MathStructure & mstruct)1114 bool has_prefix(const MathStructure &mstruct) {
1115 if(mstruct.isUnit()) return mstruct.prefix() != NULL;
1116 for(size_t i = 0; i < mstruct.size(); i++) {
1117 if(has_prefix(mstruct[i])) return true;
1118 }
1119 return false;
1120 }
1121
setPrefixes(const PrintOptions & po,MathStructure * parent,size_t pindex)1122 void MathStructure::setPrefixes(const PrintOptions &po, MathStructure *parent, size_t pindex) {
1123 switch(m_type) {
1124 case STRUCT_MULTIPLICATION: {
1125 bool b = false;
1126 size_t i = SIZE, im = 0;
1127 bool b_im = false;
1128 for(size_t i2 = 0; i2 < SIZE; i2++) {
1129 if(CHILD(i2).isUnit_exp()) {
1130 if(CHILD(i2).unit_exp_prefix()) {
1131 b = false;
1132 return;
1133 }
1134 if(!b) {
1135 if(use_prefix_with_unit(CHILD(i2), po)) {
1136 b = true;
1137 if(i > i2) {i = i2; b_im = false;}
1138 } else if(i < i2) {
1139 i = i2;
1140 b_im = false;
1141 }
1142 }
1143 } else if(CHILD(i2).isPower() && CHILD(i2)[0].isMultiplication()) {
1144 for(size_t i3 = 0; i3 < CHILD(i2)[0].size(); i3++) {
1145 if(CHILD(i2)[0][i3].isUnit_exp()) {
1146 if(CHILD(i2)[0][i3].unit_exp_prefix()) {
1147 b = false;
1148 return;
1149 }
1150 if(!b) {
1151 if(use_prefix_with_unit(CHILD(i2)[0][i3], po)) {
1152 b = true;
1153 if(i > i2) {
1154 i = i2;
1155 im = i3;
1156 b_im = true;
1157 }
1158 break;
1159 } else if(i < i2 || (i == i2 && im < i3)) {
1160 i = i2;
1161 im = i3;
1162 b_im = true;
1163 }
1164 }
1165 }
1166 }
1167 }
1168 }
1169 if(b) {
1170 Number exp(1, 1);
1171 Number exp2(1, 1);
1172 bool b2 = false;
1173 MathStructure *munit = NULL, *munit2 = NULL;
1174 if(b_im) munit = &CHILD(i)[0][im];
1175 else munit = &CHILD(i);
1176 if(CHILD(i).isPower()) {
1177 if(CHILD(i)[1].isNumber() && CHILD(i)[1].number().isInteger() && !CHILD(i)[1].number().isZero()) {
1178 if(b_im && munit->isPower()) {
1179 if((*munit)[1].isNumber() && (*munit)[1].number().isInteger() && !(*munit)[1].number().isZero()) {
1180 exp = CHILD(i)[1].number();
1181 exp *= (*munit)[1].number();
1182 } else {
1183 b = false;
1184 }
1185 } else {
1186 exp = CHILD(i)[1].number();
1187 }
1188 } else {
1189 b = false;
1190 }
1191 }
1192 if(po.use_denominator_prefix && !exp.isNegative()) {
1193 for(size_t i2 = i + 1; i2 < SIZE; i2++) {
1194 if(CALCULATOR->aborted()) break;
1195 if(CHILD(i2).isPower() && CHILD(i2)[1].isNumber() && CHILD(i2)[1].number().isNegative()) {
1196 if(CHILD(i2)[0].isUnit() && use_prefix_with_unit(CHILD(i2)[0], po)) {
1197 munit2 = &CHILD(i2)[0];
1198 if(munit2->prefix() || !CHILD(i2)[1].number().isInteger()) {
1199 break;
1200 }
1201 if(!b) {
1202 b = true;
1203 exp = CHILD(i2)[1].number();
1204 munit = munit2;
1205 } else {
1206 b2 = true;
1207 exp2 = CHILD(i2)[1].number();
1208 }
1209 break;
1210 } else if(CHILD(i2)[0].isMultiplication()) {
1211 bool b_break = false;
1212 for(size_t im2 = 0; im2 < CHILD(i2)[0].size(); im2++) {
1213 if(CHILD(i2)[0][im2].isUnit_exp() && use_prefix_with_unit(CHILD(i2)[0][im2], po) && (CHILD(i2)[0][im2].isUnit() || (CHILD(i2)[0][im2][1].isNumber() && (CHILD(i2)[0][im2][1].number().isPositive() || (!b && CHILD(i2)[0][im2][1].number().isNegative())) && CHILD(i2)[0][im2][1].number().isInteger()))) {
1214 Number exp_multi(1);
1215 if(CHILD(i2)[0][im2].isUnit()) {
1216 munit2 = &CHILD(i2)[0][im2];
1217 } else {
1218 munit2 = &CHILD(i2)[0][im2][0];
1219 exp_multi = CHILD(i2)[0][im2][1].number();
1220 }
1221 b_break = true;
1222 if(munit2->prefix() || !CHILD(i2)[1].number().isInteger()) {
1223 break;
1224 }
1225 if(!b) {
1226 b = true;
1227 exp = CHILD(i2)[1].number();
1228 exp *= exp_multi;
1229 i = i2;
1230 } else {
1231 b2 = true;
1232 exp2 = CHILD(i2)[1].number();
1233 exp2 *= exp_multi;
1234 }
1235 break;
1236 }
1237 }
1238 if(b_break) break;
1239 }
1240 }
1241 }
1242 } else if(exp.isNegative() && b) {
1243 bool had_unit = false;
1244 for(size_t i2 = i + 1; i2 < SIZE; i2++) {
1245 if(CALCULATOR->aborted()) break;
1246 bool b3 = false;
1247 if(CHILD(i2).isPower() && CHILD(i2)[1].isNumber() && CHILD(i2)[1].number().isPositive()) {
1248 if(CHILD(i2)[0].isUnit()) {
1249 if(!use_prefix_with_unit(CHILD(i2)[0], po)) {
1250 had_unit = true;
1251 } else {
1252 munit2 = &CHILD(i2);
1253 if(munit2->prefix() || !CHILD(i2)[1].number().isInteger()) {
1254 break;
1255 }
1256 b3 = true;
1257 exp2 = exp;
1258 exp = CHILD(i2)[1].number();
1259 }
1260 } else if(CHILD(i2)[0].isMultiplication()) {
1261 bool b_break = false;
1262 for(size_t im2 = 0; im2 < CHILD(i2)[0].size(); im2++) {
1263 if(CHILD(i2)[0][im2].isUnit_exp() && (CHILD(i2)[0][im2].isUnit() || (CHILD(i2)[0][im2][1].isNumber() && CHILD(i2)[0][im2][1].number().isPositive() && CHILD(i2)[0][im2][1].number().isInteger()))) {
1264 if(!use_prefix_with_unit(CHILD(i2)[0][im2], po)) {
1265 had_unit = true;
1266 } else {
1267 Number exp_multi(1);
1268 if(CHILD(i2)[0][im2].isUnit()) {
1269 munit2 = &CHILD(i2)[0][im2];
1270 } else {
1271 munit2 = &CHILD(i2)[0][im2][0];
1272 exp_multi = CHILD(i2)[0][im2][1].number();
1273 }
1274 b_break = true;
1275 if(munit2->prefix() || !CHILD(i2)[1].number().isInteger()) {
1276 break;
1277 }
1278 exp2 = exp;
1279 exp = CHILD(i2)[1].number();
1280 exp *= exp_multi;
1281 b3 = true;
1282 break;
1283 }
1284 }
1285 }
1286 if(b_break) break;
1287 }
1288 } else if(CHILD(i2).isUnit()) {
1289 if(!use_prefix_with_unit(CHILD(i2), po)) {
1290 had_unit = true;
1291 } else {
1292 if(CHILD(i2).prefix()) break;
1293 exp2 = exp;
1294 exp.set(1, 1, 0);
1295 b3 = true;
1296 munit2 = &CHILD(i2);
1297 }
1298 }
1299 if(b3) {
1300 if(po.use_denominator_prefix) {
1301 b2 = true;
1302 MathStructure *munit3 = munit;
1303 munit = munit2;
1304 munit2 = munit3;
1305 } else {
1306 munit = munit2;
1307 }
1308 had_unit = false;
1309 break;
1310 }
1311 }
1312 if(had_unit && !po.use_denominator_prefix) b = false;
1313 }
1314 Number exp10;
1315 if(b) {
1316 if(po.prefix) {
1317 if(po.prefix != CALCULATOR->getDecimalNullPrefix() && po.prefix != CALCULATOR->getBinaryNullPrefix()) {
1318 if(munit->isUnit()) munit->setPrefix(po.prefix);
1319 else (*munit)[0].setPrefix(po.prefix);
1320 if(CHILD(0).isNumber()) {
1321 CHILD(0).number() /= po.prefix->value(exp);
1322 } else {
1323 PREPEND(po.prefix->value(exp));
1324 CHILD(0).number().recip();
1325 }
1326 }
1327 } else if(po.use_unit_prefixes && CHILD(0).isNumber() && exp.isInteger()) {
1328 exp10 = CHILD(0).number();
1329 exp10.abs();
1330 exp10.intervalToMidValue();
1331 if(exp10.isLessThanOrEqualTo(Number(1, 1, 1000)) && exp10.isGreaterThanOrEqualTo(Number(1, 1, -1000))) {
1332 bool use_binary_prefix = (CALCULATOR->usesBinaryPrefixes() > 1 || (CALCULATOR->usesBinaryPrefixes() == 1 && ((munit->isUnit() && munit->unit()->baseUnit()->referenceName() == "bit") || (munit->isPower() && (*munit)[0].unit()->baseUnit()->referenceName() == "bit"))));
1333 exp10.log(use_binary_prefix ? 2 : 10);
1334 exp10.intervalToMidValue();
1335 exp10.floor();
1336 if(b2 && exp10.isPositive() && (CALCULATOR->usesBinaryPrefixes() > 1 || (CALCULATOR->usesBinaryPrefixes() == 1 && ((munit2->isUnit() && munit2->unit()->baseUnit()->referenceName() == "bit") || (munit2->isPower() && (*munit2)[0].unit()->baseUnit()->referenceName() == "bit"))))) b2 = false;
1337 if(b2 && use_binary_prefix && CALCULATOR->usesBinaryPrefixes() == 1 && exp10.isNegative()) {
1338 exp10.clear();
1339 } else if(b2) {
1340 Number tmp_exp(exp10);
1341 tmp_exp.setNegative(false);
1342 Number e1(use_binary_prefix ? 10 : 3, 1, 0);
1343 e1 *= exp;
1344 Number e2(use_binary_prefix ? 10 : 3, 1, 0);
1345 e2 *= exp2;
1346 e2.setNegative(false);
1347 int i4 = 0;
1348 while(true) {
1349 tmp_exp -= e1;
1350 if(!tmp_exp.isPositive()) {
1351 break;
1352 }
1353 if(exp10.isNegative()) i4++;
1354 tmp_exp -= e2;
1355 if(tmp_exp.isNegative()) {
1356 break;
1357 }
1358 if(!exp10.isNegative()) i4++;
1359 }
1360 e2.setNegative(exp10.isNegative());
1361 e2 *= i4;
1362 exp10 -= e2;
1363 }
1364 Prefix *p = (use_binary_prefix > 0 ? (Prefix*) CALCULATOR->getOptimalBinaryPrefix(exp10, exp) : (Prefix*) CALCULATOR->getOptimalDecimalPrefix(exp10, exp, po.use_all_prefixes));
1365 if(p) {
1366 Number test_exp(exp10);
1367 if(use_binary_prefix) test_exp -= ((BinaryPrefix*) p)->exponent(exp);
1368 else test_exp -= ((DecimalPrefix*) p)->exponent(exp);
1369 if(test_exp.isInteger()) {
1370 if((exp10.isPositive() && exp10.compare(test_exp) == COMPARISON_RESULT_LESS) || (exp10.isNegative() && exp10.compare(test_exp) == COMPARISON_RESULT_GREATER)) {
1371 CHILD(0).number() /= p->value(exp);
1372 if(munit->isUnit()) munit->setPrefix(p);
1373 else (*munit)[0].setPrefix(p);
1374 }
1375 }
1376 }
1377 }
1378 } else if(!po.use_unit_prefixes) {
1379 Prefix *p = NULL;
1380 if((munit->isUnit() && munit->unit()->referenceName() == "g") || (munit->isPower() && (*munit)[0].unit()->referenceName() == "g")) {
1381 p = CALCULATOR->getExactDecimalPrefix(3);
1382 } else if((munit->isUnit() && munit->unit()->referenceName() == "a") || (munit->isPower() && (*munit)[0].unit()->referenceName() == "a")) {
1383 p = CALCULATOR->getExactDecimalPrefix(2);
1384 }
1385 if(p) {
1386 if(munit->isUnit()) munit->setPrefix(p);
1387 else (*munit)[0].setPrefix(p);
1388 if(CHILD(0).isNumber()) {
1389 CHILD(0).number() /= p->value(exp);
1390 } else {
1391 PREPEND(p->value(exp));
1392 CHILD(0).number().recip();
1393 }
1394 }
1395 }
1396 if(b2 && CHILD(0).isNumber() && (po.prefix || po.use_unit_prefixes) && (po.prefix != CALCULATOR->getDecimalNullPrefix() && po.prefix != CALCULATOR->getBinaryNullPrefix())) {
1397 exp10 = CHILD(0).number();
1398 exp10.abs();
1399 exp10.intervalToMidValue();
1400 if(exp10.isLessThanOrEqualTo(Number(1, 1, 1000)) && exp10.isGreaterThanOrEqualTo(Number(1, 1, -1000))) {
1401 bool use_binary_prefix = (CALCULATOR->usesBinaryPrefixes() > 1 || (CALCULATOR->usesBinaryPrefixes() == 1 && ((munit2->isUnit() && munit2->unit()->baseUnit()->referenceName() == "bit") || (munit2->isPower() && (*munit2)[0].unit()->baseUnit()->referenceName() == "bit"))));
1402 exp10.log(use_binary_prefix ? 2 : 10);
1403 exp10.intervalToMidValue();
1404 exp10.floor();
1405 Prefix *p = (use_binary_prefix > 0 ? (Prefix*) CALCULATOR->getOptimalBinaryPrefix(exp10, exp2) : (Prefix*) CALCULATOR->getOptimalDecimalPrefix(exp10, exp2, po.use_all_prefixes));
1406 if(p) {
1407 Number test_exp(exp10);
1408 if(use_binary_prefix) test_exp -= ((BinaryPrefix*) p)->exponent(exp2);
1409 else test_exp -= ((DecimalPrefix*) p)->exponent(exp2);
1410 if(test_exp.isInteger()) {
1411 if((exp10.isPositive() && exp10.compare(test_exp) == COMPARISON_RESULT_LESS) || (exp10.isNegative() && exp10.compare(test_exp) == COMPARISON_RESULT_GREATER)) {
1412 CHILD(0).number() /= p->value(exp2);
1413 if(munit2->isUnit()) munit2->setPrefix(p);
1414 else (*munit2)[0].setPrefix(p);
1415 }
1416 }
1417 }
1418 }
1419 }
1420 }
1421 return;
1422 }
1423 break;
1424 }
1425 case STRUCT_UNIT: {
1426 if(!o_prefix && (po.prefix && po.prefix != CALCULATOR->getDecimalNullPrefix() && po.prefix != CALCULATOR->getBinaryNullPrefix())) {
1427 transform(STRUCT_MULTIPLICATION, m_one);
1428 SWAP_CHILDREN(0, 1);
1429 setPrefixes(po, parent, pindex);
1430 }
1431 return;
1432 }
1433 case STRUCT_POWER: {
1434 if(CHILD(0).isUnit()) {
1435 if(CHILD(1).isNumber() && CHILD(1).number().isReal() && !CHILD(0).prefix() && !o_prefix && (po.prefix && po.prefix != CALCULATOR->getDecimalNullPrefix() && po.prefix != CALCULATOR->getBinaryNullPrefix())) {
1436 transform(STRUCT_MULTIPLICATION, m_one);
1437 SWAP_CHILDREN(0, 1);
1438 setPrefixes(po, parent, pindex);
1439 }
1440 return;
1441 }
1442 break;
1443 }
1444 default: {}
1445 }
1446 if(po.prefix || !has_prefix(*this)) {
1447 for(size_t i = 0; i < SIZE; i++) {
1448 if(CALCULATOR->aborted()) break;
1449 CHILD(i).setPrefixes(po, this, i + 1);
1450 }
1451 }
1452 }
1453 bool split_unit_powers(MathStructure &mstruct);
split_unit_powers(MathStructure & mstruct)1454 bool split_unit_powers(MathStructure &mstruct) {
1455 bool b = false;
1456 for(size_t i = 0; i < mstruct.size(); i++) {
1457 if(CALCULATOR->aborted()) break;
1458 if(split_unit_powers(mstruct[i])) {
1459 mstruct.childUpdated(i + 1);
1460 b = true;
1461 }
1462 }
1463 if(mstruct.isPower() && mstruct[0].isMultiplication()) {
1464 bool b2 = mstruct[1].isNumber();
1465 for(size_t i = 0; i < mstruct[0].size(); i++) {
1466 if(mstruct[0][i].isPower() && (!b2 || !mstruct[0][i][1].isNumber())) return b;
1467 }
1468 MathStructure mpower(mstruct[1]);
1469 mstruct.setToChild(1);
1470 for(size_t i = 0; i < mstruct.size(); i++) {
1471 if(mstruct[i].isPower()) mstruct[i][1].number() *= mpower.number();
1472 else mstruct[i].raise(mpower);
1473 }
1474 mstruct.childrenUpdated();
1475 return true;
1476 }
1477 return b;
1478 }
postFormatUnits(const PrintOptions & po,MathStructure * parent,size_t)1479 void MathStructure::postFormatUnits(const PrintOptions &po, MathStructure *parent, size_t) {
1480 switch(m_type) {
1481 case STRUCT_DIVISION: {
1482 if(po.place_units_separately) {
1483 vector<size_t> nums;
1484 bool b1 = false, b2 = false;
1485 if(CHILD(0).isMultiplication()) {
1486 for(size_t i = 0; i < CHILD(0).size(); i++) {
1487 if(CHILD(0)[i].isUnit_exp()) {
1488 nums.push_back(i);
1489 } else {
1490 b1 = true;
1491 }
1492 }
1493 b1 = b1 && !nums.empty();
1494 } else if(CHILD(0).isUnit_exp()) {
1495 b1 = true;
1496 }
1497 vector<size_t> dens;
1498 if(CHILD(1).isMultiplication()) {
1499 for(size_t i = 0; i < CHILD(1).size(); i++) {
1500 if(CHILD(1)[i].isUnit_exp()) {
1501 dens.push_back(i);
1502 } else {
1503 b2 = true;
1504 }
1505 }
1506 b2 = b2 && !dens.empty();
1507 } else if(CHILD(1).isUnit_exp()) {
1508 if(CHILD(0).isUnit_exp()) {
1509 b1 = false;
1510 } else {
1511 b2 = true;
1512 }
1513 }
1514 if(b2 && !b1) b1 = true;
1515 if(b1) {
1516 MathStructure num = m_undefined;
1517 if(CHILD(0).isUnit_exp()) {
1518 num = CHILD(0);
1519 CHILD(0).set(m_one);
1520 } else if(nums.size() > 0) {
1521 num = CHILD(0)[nums[0]];
1522 for(size_t i = 1; i < nums.size(); i++) {
1523 num.multiply(CHILD(0)[nums[i]], i > 1);
1524 }
1525 for(size_t i = 0; i < nums.size(); i++) {
1526 CHILD(0).delChild(nums[i] + 1 - i);
1527 }
1528 if(CHILD(0).size() == 1) {
1529 CHILD(0).setToChild(1, true);
1530 }
1531 }
1532 MathStructure den = m_undefined;
1533 if(CHILD(1).isUnit_exp()) {
1534 den = CHILD(1);
1535 setToChild(1, true);
1536 } else if(dens.size() > 0) {
1537 den = CHILD(1)[dens[0]];
1538 for(size_t i = 1; i < dens.size(); i++) {
1539 den.multiply(CHILD(1)[dens[i]], i > 1);
1540 }
1541 for(size_t i = 0; i < dens.size(); i++) {
1542 CHILD(1).delChild(dens[i] + 1 - i);
1543 }
1544 if(CHILD(1).size() == 1) {
1545 CHILD(1).setToChild(1, true);
1546 }
1547 }
1548 if(num.isUndefined()) {
1549 transform(STRUCT_DIVISION, den);
1550 } else {
1551 if(!den.isUndefined()) {
1552 num.transform(STRUCT_DIVISION, den);
1553 }
1554 multiply(num, false);
1555 }
1556 if(CHILD(0).isDivision()) {
1557 if(CHILD(0)[0].isMultiplication()) {
1558 if(CHILD(0)[0].size() == 1) {
1559 CHILD(0)[0].setToChild(1, true);
1560 } else if(CHILD(0)[0].size() == 0) {
1561 CHILD(0)[0] = 1;
1562 }
1563 }
1564 if(CHILD(0)[1].isMultiplication()) {
1565 if(CHILD(0)[1].size() == 1) {
1566 CHILD(0)[1].setToChild(1, true);
1567 } else if(CHILD(0)[1].size() == 0) {
1568 CHILD(0).setToChild(1, true);
1569 }
1570 } else if(CHILD(0)[1].isOne()) {
1571 CHILD(0).setToChild(1, true);
1572 }
1573 if(CHILD(0).isDivision() && CHILD(0)[1].isNumber() && CHILD(0)[0].isMultiplication() && CHILD(0)[0].size() > 1 && CHILD(0)[0][0].isNumber()) {
1574 MathStructure *msave = new MathStructure;
1575 if(CHILD(0)[0].size() == 2) {
1576 msave->set(CHILD(0)[0][1]);
1577 CHILD(0)[0].setToChild(1, true);
1578 } else {
1579 msave->set(CHILD(0)[0]);
1580 CHILD(0)[0].setToChild(1, true);
1581 msave->delChild(1);
1582 }
1583 if(isMultiplication()) {
1584 insertChild_nocopy(msave, 2);
1585 } else {
1586 CHILD(0).multiply_nocopy(msave);
1587 }
1588 }
1589 }
1590 bool do_plural = po.short_multiplication;
1591 CHILD(0).postFormatUnits(po, this, 1);
1592 CHILD_UPDATED(0);
1593 switch(CHILD(0).type()) {
1594 case STRUCT_NUMBER: {
1595 if(CHILD(0).isZero() || CHILD(0).number().isOne() || CHILD(0).number().isMinusOne() || CHILD(0).number().isFraction()) {
1596 do_plural = false;
1597 }
1598 break;
1599 }
1600 case STRUCT_DIVISION: {
1601 if(CHILD(0)[0].isNumber() && CHILD(0)[1].isNumber()) {
1602 if(CHILD(0)[0].number().isLessThanOrEqualTo(CHILD(0)[1].number())) {
1603 do_plural = false;
1604 }
1605 }
1606 break;
1607 }
1608 case STRUCT_INVERSE: {
1609 if(CHILD(0)[0].isNumber() && CHILD(0)[0].number().isGreaterThanOrEqualTo(1)) {
1610 do_plural = false;
1611 }
1612 break;
1613 }
1614 default: {}
1615 }
1616 split_unit_powers(CHILD(1));
1617 switch(CHILD(1).type()) {
1618 case STRUCT_UNIT: {
1619 CHILD(1).setPlural(do_plural);
1620 break;
1621 }
1622 case STRUCT_POWER: {
1623 CHILD(1)[0].setPlural(do_plural);
1624 break;
1625 }
1626 case STRUCT_MULTIPLICATION: {
1627 if(po.limit_implicit_multiplication) CHILD(1)[0].setPlural(do_plural);
1628 else CHILD(1)[CHILD(1).size() - 1].setPlural(do_plural);
1629 break;
1630 }
1631 case STRUCT_DIVISION: {
1632 switch(CHILD(1)[0].type()) {
1633 case STRUCT_UNIT: {
1634 CHILD(1)[0].setPlural(do_plural);
1635 break;
1636 }
1637 case STRUCT_POWER: {
1638 CHILD(1)[0][0].setPlural(do_plural);
1639 break;
1640 }
1641 case STRUCT_MULTIPLICATION: {
1642 if(po.limit_implicit_multiplication) CHILD(1)[0][0].setPlural(do_plural);
1643 else CHILD(1)[0][CHILD(1)[0].size() - 1].setPlural(do_plural);
1644 break;
1645 }
1646 default: {}
1647 }
1648 break;
1649 }
1650 default: {}
1651 }
1652 }
1653 } else {
1654 for(size_t i = 0; i < SIZE; i++) {
1655 if(CALCULATOR->aborted()) break;
1656 CHILD(i).postFormatUnits(po, this, i + 1);
1657 CHILD_UPDATED(i);
1658 }
1659 }
1660 break;
1661 }
1662 case STRUCT_UNIT: {
1663 b_plural = false;
1664 break;
1665 }
1666 case STRUCT_MULTIPLICATION: {
1667 if(SIZE > 1 && CHILD(1).isUnit_exp() && CHILD(0).isNumber()) {
1668 bool do_plural = po.short_multiplication && !(CHILD(0).isZero() || CHILD(0).number().isOne() || CHILD(0).number().isMinusOne() || CHILD(0).number().isFraction());
1669 size_t i = 2;
1670 for(; i < SIZE; i++) {
1671 if(CALCULATOR->aborted()) break;
1672 if(CHILD(i).isUnit()) {
1673 CHILD(i).setPlural(false);
1674 } else if(CHILD(i).isPower() && CHILD(i)[0].isUnit()) {
1675 CHILD(i)[0].setPlural(false);
1676 } else {
1677 break;
1678 }
1679 }
1680 if(do_plural) {
1681 if(po.limit_implicit_multiplication) i = 1;
1682 else i--;
1683 if(CHILD(i).isUnit()) {
1684 CHILD(i).setPlural(true);
1685 } else {
1686 CHILD(i)[0].setPlural(true);
1687 }
1688 }
1689 } else if(SIZE > 0) {
1690 int last_unit = -1;
1691 for(size_t i = 0; i < SIZE; i++) {
1692 if(CALCULATOR->aborted()) break;
1693 if(CHILD(i).isUnit()) {
1694 CHILD(i).setPlural(false);
1695 if(!po.limit_implicit_multiplication || last_unit < 0) {
1696 last_unit = i;
1697 }
1698 } else if(CHILD(i).isPower() && CHILD(i)[0].isUnit()) {
1699 CHILD(i)[0].setPlural(false);
1700 if(!po.limit_implicit_multiplication || last_unit < 0) {
1701 last_unit = i;
1702 }
1703 } else if(last_unit >= 0) {
1704 break;
1705 }
1706 }
1707 if(po.short_multiplication && last_unit > 0) {
1708 if(CHILD(last_unit).isUnit()) {
1709 CHILD(last_unit).setPlural(true);
1710 } else {
1711 CHILD(last_unit)[0].setPlural(true);
1712 }
1713 }
1714 }
1715 break;
1716 }
1717 case STRUCT_POWER: {
1718 if(CHILD(0).isUnit()) {
1719 CHILD(0).setPlural(false);
1720 break;
1721 }
1722 }
1723 case STRUCT_NEGATE: {
1724 if(po.place_units_separately && (!parent || !parent->isAddition())) {
1725 CHILD(0).postFormatUnits(po, this, 1);
1726 CHILD_UPDATED(0);
1727 if(CHILD(0).isMultiplication() && SIZE > 0 && ((CHILD(0)[0].isDivision() && CHILD(0)[0][0].isInteger() && CHILD(0)[0][1].isInteger()) || (CHILD(0)[0].isInverse() && CHILD(0)[0][0].isInteger()))) {
1728 setToChild(1, true);
1729 CHILD(0).transform(STRUCT_NEGATE);
1730 }
1731 break;
1732 }
1733 }
1734 default: {
1735 for(size_t i = 0; i < SIZE; i++) {
1736 if(CALCULATOR->aborted()) break;
1737 CHILD(i).postFormatUnits(po, this, i + 1);
1738 CHILD_UPDATED(i);
1739 }
1740 }
1741 }
1742 }
prefixCurrencies(const PrintOptions & po)1743 void MathStructure::prefixCurrencies(const PrintOptions &po) {
1744 if(isMultiplication()) {
1745 int index = -1;
1746 for(size_t i = 0; i < SIZE; i++) {
1747 if(CALCULATOR->aborted()) break;
1748 if(CHILD(i).isUnit_exp()) {
1749 if(CHILD(i).isUnit() && CHILD(i).unit()->isCurrency()) {
1750 const ExpressionName *ename = &CHILD(i).unit()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, CHILD(i).isPlural(), po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg);
1751 bool do_prefix = false;
1752 if(ename->reference) do_prefix = (hasNegativeSign() ? CALCULATOR->place_currency_code_before_negative : CALCULATOR->place_currency_code_before);
1753 else if(ename->abbreviation) do_prefix = (hasNegativeSign() ? CALCULATOR->place_currency_sign_before_negative : CALCULATOR->place_currency_sign_before);
1754 if(!do_prefix || index >= 0) {
1755 index = -1;
1756 break;
1757 }
1758 index = i;
1759 } else {
1760 index = -1;
1761 break;
1762 }
1763 }
1764 }
1765 if(index >= 0) {
1766 v_order.insert(v_order.begin(), v_order[index]);
1767 v_order.erase(v_order.begin() + (index + 1));
1768 }
1769 } else {
1770 for(size_t i = 0; i < SIZE; i++) {
1771 if(CALCULATOR->aborted()) break;
1772 CHILD(i).prefixCurrencies(po);
1773 }
1774 }
1775 }
remove_multi_one(MathStructure & mstruct)1776 void remove_multi_one(MathStructure &mstruct) {
1777 if(mstruct.isMultiplication() && mstruct.size() > 1) {
1778 if(mstruct[0].isOne() && !mstruct[1].isUnit_exp() && (mstruct.size() != 2 || !mstruct[1].isFunction() || mstruct[1].function()->referenceName() != "cis" || mstruct[1].size() != 1)) {
1779 if(mstruct.size() == 2) mstruct.setToChild(2, true);
1780 else mstruct.delChild(1);
1781 }
1782 }
1783 for(size_t i = 0; i < mstruct.size(); i++) {
1784 if(CALCULATOR->aborted()) break;
1785 remove_multi_one(mstruct[i]);
1786 }
1787 }
unnegate_multiplier(MathStructure & mstruct,const PrintOptions & po)1788 bool unnegate_multiplier(MathStructure &mstruct, const PrintOptions &po) {
1789 if(mstruct.isMultiplication() && mstruct.size() >= 2 && mstruct[0].isNumber() && mstruct[0].number().isNegative()) {
1790 for(size_t i = 1; i < mstruct.size(); i++) {
1791 if(CALCULATOR->aborted()) break;
1792 if(mstruct[i].isAddition() || (mstruct[i].isPower() && mstruct[i][0].isAddition() && mstruct[i][1].isMinusOne())) {
1793 MathStructure *mden;
1794 if(mstruct[i].isAddition()) mden = &mstruct[i];
1795 else mden = &mstruct[i][0];
1796 bool b_pos = false, b_neg = false;
1797 for(size_t i2 = 0; i2 < mden->size(); i2++) {
1798 if((*mden)[i2].hasNegativeSign()) {
1799 b_neg = true;
1800 } else {
1801 b_pos = true;
1802 }
1803 if(b_neg && b_pos) break;
1804 }
1805 if(b_neg && b_pos) {
1806 for(size_t i2 = 0; i2 < mden->size(); i2++) {
1807 if((*mden)[i2].isNumber()) {
1808 (*mden)[i2].number().negate();
1809 } else if((*mden)[i2].isMultiplication() && (*mden)[i2].size() > 0) {
1810 if((*mden)[i2][0].isNumber()) {
1811 if((*mden)[i2][0].number().isMinusOne() && (*mden)[i2].size() > 1) {
1812 if((*mden)[i2].size() == 2) (*mden)[i2].setToChild(2, true);
1813 else (*mden)[i2].delChild(1);
1814 } else (*mden)[i2][0].number().negate();
1815 } else {
1816 (*mden)[i2].insertChild(m_minus_one, 1);
1817 }
1818 } else {
1819 (*mden)[i2].negate();
1820 }
1821 }
1822 mden->sort(po, false);
1823 if(mstruct[0].number().isMinusOne()) {
1824 if(mstruct.size() == 2) mstruct.setToChild(2, true);
1825 else mstruct.delChild(1);
1826 } else {
1827 mstruct[0].number().negate();
1828 }
1829 return true;
1830 }
1831 }
1832 }
1833 }
1834 bool b = false;
1835 for(size_t i = 0; i < mstruct.size(); i++) {
1836 if(CALCULATOR->aborted()) break;
1837 if(unnegate_multiplier(mstruct[i], po)) {
1838 b = true;
1839 }
1840 }
1841 if(b) {
1842 mstruct.sort(po, false);
1843 return true;
1844 }
1845 return false;
1846 }
default_angle_unit(const EvaluationOptions & eo)1847 Unit *default_angle_unit(const EvaluationOptions &eo) {
1848 switch(eo.parse_options.angle_unit) {
1849 case ANGLE_UNIT_DEGREES: {return CALCULATOR->getDegUnit();}
1850 case ANGLE_UNIT_GRADIANS: {return CALCULATOR->getGraUnit();}
1851 case ANGLE_UNIT_RADIANS: {return CALCULATOR->getRadUnit();}
1852 default: {}
1853 }
1854 return NULL;
1855 }
1856
remove_angle_unit(MathStructure & m,Unit * u)1857 bool remove_angle_unit(MathStructure &m, Unit *u) {
1858 // remove angle unit from trigonometric function arguments
1859 bool b_ret = false;
1860 for(size_t i = 0; i < m.size(); i++) {
1861 if(remove_angle_unit(m[i], u)) b_ret = true;
1862 if(m.isFunction() && m.function()->getArgumentDefinition(i + 1) && m.function()->getArgumentDefinition(i + 1)->type() == ARGUMENT_TYPE_ANGLE) {
1863 if(m[i].isUnit() && !m[i].prefix() && m[i].unit() == u) {
1864 m[i].set(1, 1, 0, true);
1865 } else if(m[i].isMultiplication()) {
1866 // f(a)*u: f(a)
1867 for(size_t i3 = 0; i3 < m[i].size(); i3++) {
1868 // ignore units with prefix
1869 if(m[i][i3].isUnit() && !m[i][i3].prefix() && m[i][i3].unit() == u) {
1870 m[i].delChild(i3 + 1, true);
1871 b_ret = true;
1872 break;
1873 }
1874 }
1875 } else if(m[i].isAddition()) {
1876 bool b = true;
1877 // f(a)*u+f(b)*u: f(a)+f(b)
1878 // check if unit is present in all terms first
1879 for(size_t i2 = 0; i2 < m[i].size(); i2++) {
1880 bool b2 = false;
1881 if(m[i][i2].isUnit() && !m[i][i2].prefix() && m[i][i2].unit() == u) {
1882 b2 = true;
1883 } else if(m[i][i2].isMultiplication()) {
1884 for(size_t i3 = 0; i3 < m[i][i2].size(); i3++) {
1885 if(m[i][i2][i3].isUnit() && !m[i][i2][i3].prefix() && m[i][i2][i3].unit() == u) {
1886 b2 = true;
1887 break;
1888 }
1889 }
1890 }
1891 if(!b2) {
1892 b = false;
1893 break;
1894 }
1895 }
1896 if(b) {
1897 b_ret = true;
1898 for(size_t i2 = 0; i2 < m[i].size(); i2++) {
1899 if(m[i][i2].isUnit() && !m[i][i2].prefix() && m[i][i2].unit() == u) {
1900 m[i][i2].set(1, 1, 0, true);
1901 } else {
1902 for(size_t i3 = 0; i3 < m[i][i2].size(); i3++) {
1903 if(m[i][i2][i3].isUnit() && !m[i][i2][i3].prefix() && m[i][i2][i3].unit() == u) {
1904 m[i][i2].delChild(i3 + 1, true);
1905 break;
1906 }
1907 }
1908 }
1909 }
1910 }
1911 }
1912 }
1913 }
1914 return b_ret;
1915 }
removeDefaultAngleUnit(const EvaluationOptions & eo)1916 bool MathStructure::removeDefaultAngleUnit(const EvaluationOptions &eo) {
1917 // remove default angle unit from trigonometric function arguments
1918 Unit *u = default_angle_unit(eo);
1919 if(!u) return false;
1920 return remove_angle_unit(*this, u);
1921 }
separate_units(MathStructure & m,MathStructure * parent=NULL,size_t index=0)1922 void separate_units(MathStructure &m, MathStructure *parent = NULL, size_t index = 0) {
1923 if(m.isMultiplication() && parent && parent->isMultiplication() && m.containsType(STRUCT_UNIT, false, false, false)) {
1924 for(size_t i = 0; i < m.size();) {
1925 if(m[i].isUnit_exp()) {
1926 m[i].ref();
1927 parent->addChild_nocopy(&m[i]);
1928 m.delChild(i + 1);
1929 } else {
1930 i++;
1931 }
1932 }
1933 if(m.size() == 0) parent->delChild(index);
1934 else if(m.size() == 1) m.setToChild(1, true);
1935 } else if(m.isPower() && m[1].isNumber() && m[1].number().isReal() && m[0].isMultiplication() && m[0].containsType(STRUCT_UNIT, false, false, false)) {
1936 MathStructure units;
1937 for(size_t i = 0; i < m[0].size();) {
1938 if(m[0][i].isUnit() || (m[0][i].isPower() && m[0][i][0].isUnit() && m[0][i][1].isNumber() && m[0][i][1].number().isReal())) {
1939 if(!m[0][i].isPower() || !m[0][i][1].number().multiply(m[1].number())) {
1940 m[0][i].raise(m[1]);
1941 }
1942 m[0][i].ref();
1943 units.addChild_nocopy(&m[0][i]);
1944 m[0].delChild(i + 1);
1945 } else {
1946 i++;
1947 }
1948 }
1949 if(units.size() > 0) {
1950 if((!parent || !parent->isMultiplication()) && m[0].size() == 0) {
1951 if(units.size() == 1) units.setToChild(1);
1952 else units.setType(STRUCT_MULTIPLICATION);
1953 m.set_nocopy(units, true);
1954 } else {
1955 if(parent && parent->isMultiplication() && m[0].size() == 0) parent->delChild(index);
1956 else if(m[0].size() == 1) m[0].setToChild(1, true);
1957 for(size_t i = 0; i < units.size(); i++) {
1958 units[i].ref();
1959 if(parent && parent->isMultiplication()) parent->addChild_nocopy(&units[i]);
1960 else m.multiply_nocopy(&units[i], true);
1961 }
1962 }
1963 }
1964 }
1965 for(size_t i = 0; i < m.size(); i++) {
1966 separate_units(m[i], &m, i + 1);
1967 }
1968 }
1969
format(const PrintOptions & po)1970 void MathStructure::format(const PrintOptions &po) {
1971 if(!po.preserve_format) {
1972 if(po.place_units_separately) {
1973 // a*u+b*u=(a+b)*u
1974 factorizeUnits();
1975 separate_units(*this);
1976 }
1977 sort(po);
1978 // 5000 u = 5 ku
1979 setPrefixes(po);
1980 // -1/(a-b)=1/(b-a)
1981 unnegate_multiplier(*this, po);
1982 // a(bx+y)=abx+ay if a and/or b are rational number displayed approximately
1983 fix_approximate_multiplier(*this, po);
1984 if(po.improve_division_multipliers) {
1985 // 0.5x/y=x/(2y)
1986 if(improve_division_multipliers(po)) sort(po);
1987 }
1988 // 1*a=a
1989 remove_multi_one(*this);
1990 }
1991 formatsub(po, NULL, 0, true, this);
1992 if(!po.preserve_format) {
1993 postFormatUnits(po);
1994 if(po.sort_options.prefix_currencies) {
1995 prefixCurrencies(po);
1996 }
1997 }
1998 }
1999
is_unit_multiadd(const MathStructure & m)2000 bool is_unit_multiadd(const MathStructure &m) {
2001 for(size_t i = 0; i < m.size(); i++) {
2002 if(!is_unit_multiexp(m[i]) && (!m[i].isMultiplication() || m[i].size() <= 1 || !m[i][0].isNumber() || !is_unit_multiexp(m[i][1]))) return false;
2003 }
2004 return true;
2005 }
2006
formatsub(const PrintOptions & po,MathStructure * parent,size_t pindex,bool recursive,MathStructure * top_parent)2007 void MathStructure::formatsub(const PrintOptions &po, MathStructure *parent, size_t pindex, bool recursive, MathStructure *top_parent) {
2008
2009 if(recursive) {
2010 size_t first_neg_exp = SIZE;
2011 if(m_type == STRUCT_MULTIPLICATION && po.place_units_separately && !po.negative_exponents) {
2012 // use negative exponents (instead of division) for units if fist unit has negative exponent (this should ordinarily mean that all subsequent units also has negative exponents)
2013 for(size_t i = 0; i < SIZE; i++) {
2014 if(CHILD(i).isUnit_exp()) {
2015 if(!CHILD(i).isPower() || !CHILD(i)[1].hasNegativeSign()) break;
2016 first_neg_exp = i;
2017 break;
2018 }
2019 }
2020 }
2021 for(size_t i = 0; i < SIZE; i++) {
2022 if(CALCULATOR->aborted()) break;
2023 if(i >= first_neg_exp) {
2024 PrintOptions po2 = po;
2025 po2.negative_exponents = true;
2026 CHILD(i).formatsub(po2, this, i + 1, true, top_parent);
2027 } else if(po.number_fraction_format == FRACTION_COMBINED && (m_type == STRUCT_FUNCTION || m_type == STRUCT_POWER || (m_type == STRUCT_ADDITION && (!po.place_units_separately || !is_unit_multiadd(*this))) || (m_type == STRUCT_MULTIPLICATION && SIZE > 1 && (!po.place_units_separately || !CHILD(0).isNumber() || !is_unit_multiexp(CHILD(1)))))) {
2028 PrintOptions po2 = po;
2029 po2.number_fraction_format = FRACTION_FRACTIONAL;
2030 CHILD(i).formatsub(po2, this, i + 1, true, top_parent);
2031 } else if(!po.preserve_format && i == 1 && m_type == STRUCT_POWER && po.number_fraction_format < FRACTION_FRACTIONAL && CHILD(1).isNumber() && CHILD(1).number().isRational() && !CHILD(1).number().isInteger() && CHILD(1).number().numeratorIsLessThan(10) && CHILD(1).number().numeratorIsGreaterThan(-10) && CHILD(1).number().denominatorIsLessThan(10)) {
2032 // always display rational number exponents with small numerator and denominator as fraction (e.g. 5^(2/3) instead of 5^0.666...)
2033 PrintOptions po2 = po;
2034 po2.number_fraction_format = FRACTION_FRACTIONAL;
2035 CHILD(i).formatsub(po2, this, i + 1, false, top_parent);
2036 } else {
2037 CHILD(i).formatsub(po, this, i + 1, true, top_parent);
2038 }
2039 CHILD_UPDATED(i);
2040 }
2041 }
2042 switch(m_type) {
2043 case STRUCT_ADDITION: {
2044 break;
2045 }
2046 case STRUCT_NEGATE: {
2047 break;
2048 }
2049 case STRUCT_DIVISION: {
2050 if(po.preserve_format) break;
2051 if(CHILD(0).isAddition() && CHILD(0).size() > 0 && CHILD(0)[0].isNegate()) {
2052 // (-a-b)/(c-d)=-(a+b)/(c-d); (-a+b)/(-c-d)=(a-b)/(c+d)
2053 int imin = 1;
2054 for(size_t i = 1; i < CHILD(0).size(); i++) {
2055 if(CHILD(0)[i].isNegate()) {
2056 imin++;
2057 } else {
2058 imin--;
2059 }
2060 }
2061 bool b = CHILD(1).isAddition() && CHILD(1).size() > 0 && CHILD(1)[0].isNegate();
2062 if(b) {
2063 imin++;
2064 for(size_t i = 1; i < CHILD(1).size(); i++) {
2065 if(CHILD(1)[i].isNegate()) {
2066 imin++;
2067 } else {
2068 imin--;
2069 }
2070 }
2071 }
2072 if(imin > 0 || (imin == 0 && parent && parent->isNegate())) {
2073 for(size_t i = 0; i < CHILD(0).size(); i++) {
2074 if(CHILD(0)[i].isNegate()) {
2075 CHILD(0)[i].setToChild(1, true);
2076 } else {
2077 CHILD(0)[i].transform(STRUCT_NEGATE);
2078 }
2079 }
2080 if(b) {
2081 for(size_t i = 0; i < CHILD(1).size(); i++) {
2082 if(CHILD(1)[i].isNegate()) {
2083 CHILD(1)[i].setToChild(1, true);
2084 } else {
2085 CHILD(1)[i].transform(STRUCT_NEGATE);
2086 }
2087 }
2088 } else {
2089 transform(STRUCT_NEGATE);
2090 }
2091 break;
2092 }
2093 } else if(CHILD(1).isAddition() && CHILD(1).size() > 0 && CHILD(1)[0].isNegate()) {
2094 // (a+b)/(-c-d)=-(a+b)/(c+d)
2095 int imin = 1;
2096 for(size_t i = 1; i < CHILD(1).size(); i++) {
2097 if(CHILD(1)[i].isNegate()) {
2098 imin++;
2099 } else {
2100 imin--;
2101 }
2102 }
2103 if(imin > 0 || (imin == 0 && parent && parent->isNegate())) {
2104 for(size_t i = 0; i < CHILD(1).size(); i++) {
2105 if(CHILD(1)[i].isNegate()) {
2106 CHILD(1)[i].setToChild(1, true);
2107 } else {
2108 CHILD(1)[i].transform(STRUCT_NEGATE);
2109 }
2110 }
2111 transform(STRUCT_NEGATE);
2112 }
2113 }
2114 break;
2115 }
2116 case STRUCT_INVERSE: {
2117 if(po.preserve_format) break;
2118 if((!parent || !parent->isMultiplication()) && CHILD(0).isAddition() && CHILD(0).size() > 0 && CHILD(0)[0].isNegate()) {
2119 // (-a-b+c)^-1=-(a+b-c)^-1
2120 int imin = 1;
2121 for(size_t i = 1; i < CHILD(0).size(); i++) {
2122 if(CHILD(0)[i].isNegate()) {
2123 imin++;
2124 } else {
2125 imin--;
2126 }
2127 }
2128 if(imin > 0 || (imin == 0 && parent && parent->isNegate())) {
2129 for(size_t i = 0; i < CHILD(0).size(); i++) {
2130 if(CHILD(0)[i].isNegate()) {
2131 CHILD(0)[i].setToChild(1, true);
2132 } else {
2133 CHILD(0)[i].transform(STRUCT_NEGATE);
2134 }
2135 }
2136 transform(STRUCT_NEGATE);
2137 }
2138 }
2139 break;
2140 }
2141 case STRUCT_MULTIPLICATION: {
2142 if(po.preserve_format) break;
2143
2144 if(CHILD(0).isNegate()) {
2145 if(CHILD(0)[0].isOne()) {
2146 // (-1)x=-(x)
2147 ERASE(0);
2148 if(SIZE == 1) setToChild(1, true);
2149 } else {
2150 // -(a)x=-(ax)
2151 CHILD(0).setToChild(1, true);
2152 }
2153 formatsub(po, parent, pindex, false, top_parent);
2154 if((!parent || !parent->isAddition()) && (isMultiplication() && SIZE > 0 && ((CHILD(0).isDivision() && CHILD(0)[0].isInteger() && CHILD(0)[1].isInteger()) || (CHILD(0).isInverse() && CHILD(0)[0].isInteger())))) {
2155 CHILD(0).transform(STRUCT_NEGATE);
2156 } else {
2157 transform(STRUCT_NEGATE);
2158 }
2159 break;
2160 }
2161
2162 bool b = false;
2163 for(size_t i = 0; i < SIZE; i++) {
2164 if(CALCULATOR->aborted()) break;
2165 if(CHILD(i).isInverse()) {
2166 b = true;
2167 break;
2168 } else if(CHILD(i).isDivision()) {
2169 if(!CHILD(i)[0].isNumber() || !CHILD(i)[1].isNumber() || CHILD(i)[0].number().isOne()) {
2170 b = true;
2171 break;
2172 }
2173 }
2174 }
2175
2176 if(b) {
2177 MathStructure *den = new MathStructure();
2178 MathStructure *num = new MathStructure();
2179 num->setUndefined();
2180 short ds = 0, ns = 0;
2181 MathStructure *mnum = NULL, *mden = NULL;
2182 for(size_t i = 0; i < SIZE; i++) {
2183 if(CHILD(i).isInverse()) {
2184 mden = &CHILD(i)[0];
2185 } else if(CHILD(i).isDivision()) {
2186 mnum = &CHILD(i)[0];
2187 mden = &CHILD(i)[1];
2188 } else {
2189 mnum = &CHILD(i);
2190 }
2191 if(mnum && !mnum->isOne()) {
2192 if(ns > 0) {
2193 if(mnum->isMultiplication() && num->isNumber()) {
2194 for(size_t i2 = 0; i2 < mnum->size(); i2++) {
2195 num->multiply((*mnum)[i2], true);
2196 }
2197 } else {
2198 num->multiply(*mnum, ns > 1);
2199 }
2200 } else {
2201 num->set(*mnum);
2202 }
2203 ns++;
2204 mnum = NULL;
2205 }
2206 if(mden) {
2207 if(ds > 0) {
2208 if(mden->isMultiplication() && den->isNumber()) {
2209 for(size_t i2 = 0; i2 < mden->size(); i2++) {
2210 den->multiply((*mden)[i2], true);
2211 }
2212 } else {
2213 den->multiply(*mden, ds > 1);
2214 }
2215 } else {
2216 den->set(*mden);
2217 }
2218 ds++;
2219 mden = NULL;
2220 }
2221 }
2222 clear(true);
2223 m_type = STRUCT_DIVISION;
2224 if(num->isUndefined()) num->set(m_one);
2225 APPEND_POINTER(num);
2226 APPEND_POINTER(den);
2227 num->formatsub(po, this, 1, false, top_parent);
2228 den->formatsub(po, this, 2, false, top_parent);
2229 formatsub(po, parent, pindex, false, top_parent);
2230 break;
2231 }
2232
2233 size_t index = 0;
2234 if(CHILD(0).isOne()) {
2235 index = 1;
2236 }
2237 switch(CHILD(index).type()) {
2238 case STRUCT_POWER: {
2239 if(!CHILD(index)[0].isUnit_exp()) {
2240 break;
2241 }
2242 }
2243 case STRUCT_UNIT: {
2244 if(index == 0) {
2245 if(!parent || (!parent->isPower() && !parent->isMultiplication() && !parent->isInverse() && (!parent->isDivision() || pindex != 2))) {
2246 PREPEND(m_one);
2247 break;
2248 }
2249 }
2250 break;
2251 }
2252 case STRUCT_FUNCTION: {
2253 if(index == 1 && SIZE == 2 && CHILD(index).function()->referenceName() == "cis" && CHILD(index).size() == 1) break;
2254 }
2255 default: {
2256 if(index == 1) {
2257 ERASE(0);
2258 if(SIZE == 1) {
2259 setToChild(1, true);
2260 }
2261 break;
2262 }
2263 }
2264 }
2265 break;
2266 }
2267 case STRUCT_UNIT: {
2268 if(po.preserve_format) break;
2269 if(!parent || (!parent->isPower() && !parent->isMultiplication() && !parent->isInverse() && !(parent->isDivision() && pindex == 2))) {
2270 // u = 1 u
2271 multiply(m_one);
2272 SWAP_CHILDREN(0, 1);
2273 }
2274 break;
2275 }
2276 case STRUCT_POWER: {
2277 if(po.preserve_format) break;
2278 if(CHILD(1).isNegate() && ((!po.negative_exponents && parent != NULL) || !CHILD(0).isUnit()) && (!CHILD(0).isVector() || !CHILD(1).isMinusOne())) {
2279 if(CHILD(1)[0].isOne()) {
2280 // f(a)^-1=1/f(a)
2281 m_type = STRUCT_INVERSE;
2282 ERASE(1);
2283 } else {
2284 // f(a)^-b=1/f(a)^b
2285 CHILD(1).setToChild(1, true);
2286 transform(STRUCT_INVERSE);
2287 }
2288 formatsub(po, parent, pindex, true, top_parent);
2289 break;
2290 } else if(po.halfexp_to_sqrt && ((CHILD(1).isDivision() && CHILD(1)[0].isNumber() && CHILD(1)[0].number().isInteger() && CHILD(1)[1].isNumber() && CHILD(1)[1].number().isTwo() && (((!po.negative_exponents || !CHILD(0).isUnit()) && (CHILD(0).countChildren() == 0 || CHILD(0).isFunction())) || CHILD(1)[0].isOne())) || (CHILD(1).isNumber() && CHILD(1).number().denominatorIsTwo() && (((!po.negative_exponents || !CHILD(0).isUnit()) && (CHILD(0).countChildren() == 0 || CHILD(0).isFunction())) || CHILD(1).number().numeratorIsOne())) || (CHILD(1).isInverse() && CHILD(1)[0].isNumber() && CHILD(1)[0].number() == 2))) {
2291 if(CHILD(1).isInverse() || (CHILD(1).isDivision() && CHILD(1)[0].number().isOne()) || (CHILD(1).isNumber() && CHILD(1).number().numeratorIsOne())) {
2292 // f(a)^(1/2)=sqrt(f(a))
2293 m_type = STRUCT_FUNCTION;
2294 ERASE(1)
2295 setFunctionId(FUNCTION_ID_SQRT);
2296 } else {
2297 // f(a)^(b+1/2)=f(b)^(sqrt(f(a))
2298 if(CHILD(1).isNumber()) {
2299 // f(a)^b
2300 CHILD(1).number() -= nr_half;
2301 } else {
2302 // f(a)^(b/2)
2303 Number nr = CHILD(1)[0].number();
2304 nr /= CHILD(1)[1].number();
2305 nr.floor();
2306 CHILD(1).set(nr);
2307 }
2308 if(CHILD(1).number().isOne()) {
2309 setToChild(1, true);
2310 if(parent && parent->isMultiplication()) {
2311 parent->insertChild_nocopy(new MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_SQRT), this, NULL), pindex + 1);
2312 } else {
2313 multiply_nocopy(new MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_SQRT), this, NULL));
2314 }
2315 } else {
2316 if(parent && parent->isMultiplication()) {
2317 parent->insertChild_nocopy(new MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_SQRT), &CHILD(0), NULL), pindex + 1);
2318 } else {
2319 multiply_nocopy(new MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_SQRT), &CHILD(0), NULL));
2320 }
2321 }
2322 }
2323 formatsub(po, parent, pindex, false, top_parent);
2324 break;
2325 } else if((po.exp_to_root || po.halfexp_to_sqrt) && CHILD(0).representsNonNegative(true) && ((CHILD(1).isDivision() && CHILD(1)[0].isNumber() && CHILD(1)[0].number().isInteger() && CHILD(1)[1].isNumber() && (CHILD(1)[1].number() == 3 || (po.exp_to_root && CHILD(1)[1].number().isGreaterThan(1) && CHILD(1)[1].number().isLessThan(10))) && ((!po.negative_exponents && (CHILD(0).countChildren() == 0 || CHILD(0).isFunction())) || CHILD(1)[0].isOne())) || (CHILD(1).isNumber() && CHILD(1).number().isRational() && (CHILD(1).number().denominatorEquals(3) || (po.exp_to_root && !CHILD(1).number().isInteger() && CHILD(1).number().denominatorIsLessThan(10))) && ((!po.negative_exponents && (CHILD(0).countChildren() == 0 || CHILD(0).isFunction())) || CHILD(1).number().numeratorIsOne())) || (CHILD(1).isInverse() && CHILD(1)[0].isNumber() && (CHILD(1)[0].number() == 3 || (po.exp_to_root && CHILD(1)[0].number().isInteger() && CHILD(1)[0].number().isPositive() && CHILD(1)[0].number().isLessThan(10)))))) {
2326 // f(a)^(b/c)=root(f(a),c)^b
2327 Number nr_int, nr_num, nr_den;
2328 if(CHILD(1).isNumber()) {
2329 nr_num = CHILD(1).number().numerator();
2330 nr_den = CHILD(1).number().denominator();
2331 } else if(CHILD(1).isDivision()) {
2332 nr_num.set(CHILD(1)[0].number());
2333 nr_den.set(CHILD(1)[1].number());
2334 } else if(CHILD(1).isInverse()) {
2335 nr_num.set(1, 1, 0);
2336 nr_den.set(CHILD(1)[0].number());
2337 }
2338 if(!nr_num.isOne() && (nr_num - 1).isIntegerDivisible(nr_den)) {
2339 nr_int = nr_num;
2340 nr_int--;
2341 nr_int.divide(nr_den);
2342 nr_num = 1;
2343 }
2344 MathStructure mbase(CHILD(0));
2345 CHILD(1) = nr_den;
2346 m_type = STRUCT_FUNCTION;
2347 setFunctionId(FUNCTION_ID_ROOT);
2348 formatsub(po, parent, pindex, false, top_parent);
2349 if(!nr_num.isOne()) {
2350 raise(nr_num);
2351 formatsub(po, parent, pindex, false, top_parent);
2352 }
2353 if(!nr_int.isZero()) {
2354 if(!nr_int.isOne()) mbase.raise(nr_int);
2355 multiply(mbase);
2356 sort(po);
2357 formatsub(po, parent, pindex, false, top_parent);
2358 }
2359 break;
2360 }
2361 if(CHILD(0).isUnit_exp() && (!parent || (!parent->isPower() && !parent->isMultiplication() && !parent->isInverse() && !(parent->isDivision() && pindex == 2)))) {
2362 multiply(m_one);
2363 SWAP_CHILDREN(0, 1);
2364 }
2365 break;
2366 }
2367 case STRUCT_FUNCTION: {
2368 if(po.preserve_format) break;
2369 if(o_function->id() == FUNCTION_ID_ROOT && SIZE == 2 && CHILD(1) == 3) {
2370 // root(f(a),3)=cbrt(f(a))
2371 ERASE(1)
2372 setFunctionId(FUNCTION_ID_CBRT);
2373 } else if(o_function->id() == FUNCTION_ID_INTERVAL && SIZE == 2 && CHILD(0).isAddition() && CHILD(0).size() == 2 && CHILD(1).isAddition() && CHILD(1).size() == 2) {
2374 // interval(f(a)+c,f(a)-c)=uncertainty(f(a),c)
2375 MathStructure *mmid = NULL, *munc = NULL;
2376 if(CHILD(0)[0].equals(CHILD(1)[0], true, true)) {
2377 mmid = &CHILD(0)[0];
2378 if(CHILD(0)[1].isNegate() && CHILD(0)[1][0].equals(CHILD(1)[1], true, true)) munc = &CHILD(1)[1];
2379 if(CHILD(1)[1].isNegate() && CHILD(1)[1][0].equals(CHILD(0)[1], true, true)) munc = &CHILD(0)[1];
2380 } else if(CHILD(0)[1].equals(CHILD(1)[1], true, true)) {
2381 mmid = &CHILD(0)[1];
2382 if(CHILD(0)[0].isNegate() && CHILD(0)[0][0].equals(CHILD(1)[0], true, true)) munc = &CHILD(1)[0];
2383 if(CHILD(1)[0].isNegate() && CHILD(1)[0][0].equals(CHILD(0)[0], true, true)) munc = &CHILD(0)[0];
2384 } else if(CHILD(0)[0].equals(CHILD(1)[1], true, true)) {
2385 mmid = &CHILD(0)[0];
2386 if(CHILD(0)[1].isNegate() && CHILD(0)[1][0].equals(CHILD(1)[0], true, true)) munc = &CHILD(1)[0];
2387 if(CHILD(1)[0].isNegate() && CHILD(1)[0][0].equals(CHILD(0)[1], true, true)) munc = &CHILD(0)[1];
2388 } else if(CHILD(0)[1].equals(CHILD(1)[0], true, true)) {
2389 mmid = &CHILD(0)[0];
2390 if(CHILD(0)[0].isNegate() && CHILD(0)[0][0].equals(CHILD(1)[1], true, true)) munc = &CHILD(1)[1];
2391 if(CHILD(1)[1].isNegate() && CHILD(1)[1][0].equals(CHILD(0)[0], true, true)) munc = &CHILD(0)[0];
2392 }
2393 if(mmid && munc) {
2394 setFunctionId(FUNCTION_ID_UNCERTAINTY);
2395 mmid->ref();
2396 munc->ref();
2397 CLEAR
2398 APPEND_POINTER(mmid)
2399 APPEND_POINTER(munc)
2400 APPEND(m_zero)
2401 }
2402 }
2403 break;
2404 }
2405 case STRUCT_VARIABLE: {
2406 if(o_variable == CALCULATOR->getVariableById(VARIABLE_ID_PLUS_INFINITY) || o_variable == CALCULATOR->getVariableById(VARIABLE_ID_MINUS_INFINITY)) {
2407 // replace infinity variable with infinity number
2408 set(((KnownVariable*) o_variable)->get());
2409 }
2410 break;
2411 }
2412 case STRUCT_NUMBER: {
2413 bool force_fraction = false;
2414 if(!po.preserve_format && parent && parent->isMultiplication() && o_number.isRational()) {
2415 // always show fraction format for rational number a in a(f(b)+f(c))
2416 for(size_t i = 0; i < parent->size(); i++) {
2417 if((*parent)[i].isAddition()) {
2418 force_fraction = true;
2419 break;
2420 }
2421 }
2422 }
2423
2424 if((o_number.isNegative() || ((parent || po.interval_display != INTERVAL_DISPLAY_SIGNIFICANT_DIGITS) && o_number.isInterval() && o_number.isNonPositive())) && (po.base != BASE_CUSTOM || !CALCULATOR->customOutputBase().isNegative()) && (po.base > BASE_FP16 || po.base < BASE_FP80)) {
2425 if((((po.base != 2 || !po.twos_complement) && (po.base != 16 || !po.hexadecimal_twos_complement)) || !o_number.isInteger()) && (!o_number.isMinusInfinity() || (parent && parent->isAddition()))) {
2426 // a=-(-a), if a is a negative number (or a is interval from negative value to 0), and not using two's complement and not using negative number base
2427 o_number.negate();
2428 transform(STRUCT_NEGATE);
2429 formatsub(po, parent, pindex, true, top_parent);
2430 }
2431 } else if((force_fraction || po.number_fraction_format >= FRACTION_FRACTIONAL || po.base == BASE_ROMAN_NUMERALS || po.number_fraction_format == FRACTION_DECIMAL_EXACT) && po.base > BASE_FP16 && po.base != BASE_SEXAGESIMAL && po.base != BASE_TIME && o_number.isRational() && !o_number.isInteger() && (force_fraction || !o_number.isApproximate())) {
2432 // split rational number in numerator and denominator, if display of fractions is requested for rational numbers and number base is not sexagesimal and number is not approximate
2433
2434 InternalPrintStruct ips_n;
2435
2436 // parent approximate status affects the display of numbers if force_fraction is not true
2437 if(!force_fraction && (isApproximate() || (top_parent && top_parent->isApproximate()))) ips_n.parent_approximate = true;
2438
2439 // if current mode and parent precision dictates showing of ending zeroes, number is not shown as fraction
2440 if(po.show_ending_zeroes && po.restrict_to_parent_precision && ips_n.parent_approximate && po.base != BASE_ROMAN_NUMERALS && po.base != BASE_BIJECTIVE_26 && (o_number.numeratorIsGreaterThan(9) || o_number.numeratorIsLessThan(-9) || o_number.denominatorIsGreaterThan(9))) {
2441 break;
2442 }
2443 ips_n.parent_precision = precision();
2444 if(top_parent && top_parent->precision() < 0 && top_parent->precision() < ips_n.parent_precision) ips_n.parent_precision = top_parent->precision();
2445
2446 bool approximately_displayed = false;
2447 PrintOptions po2 = po;
2448 po2.is_approximate = &approximately_displayed;
2449 po2.indicate_infinite_series = false;
2450 if(force_fraction && (po2.number_fraction_format == FRACTION_DECIMAL || po2.number_fraction_format == FRACTION_DECIMAL_EXACT)) po2.number_fraction_format = FRACTION_FRACTIONAL;
2451 if(!force_fraction && po.base != BASE_ROMAN_NUMERALS && po.base != BASE_BIJECTIVE_26 && po.number_fraction_format == FRACTION_DECIMAL_EXACT) {
2452 // if FRACTION_DECIMAL_EXACT is active, numbers is not displayed as fraction if they can be shown exact using decimals
2453 po2.number_fraction_format = FRACTION_DECIMAL;
2454 o_number.print(po2, ips_n);
2455 if(!approximately_displayed) break;
2456 approximately_displayed = false;
2457 }
2458
2459 // test if numerator and denominator is displayed exact using current mode
2460 Number num(o_number.numerator());
2461 if(po.number_fraction_format == FRACTION_COMBINED) {
2462 num.mod(o_number.denominator());
2463 }
2464 Number den(o_number.denominator());
2465 if(isApproximate()) {
2466 num.setApproximate();
2467 den.setApproximate();
2468 }
2469 num.print(po2, ips_n);
2470 if(!approximately_displayed || po.base == BASE_ROMAN_NUMERALS || po.base == BASE_BIJECTIVE_26) {
2471 den.print(po2, ips_n);
2472 if(!approximately_displayed || po.base == BASE_ROMAN_NUMERALS || po.base == BASE_BIJECTIVE_26) {
2473 if(po.number_fraction_format == FRACTION_COMBINED && !o_number.isFraction()) {
2474 // mixed fraction format (e.g. 5/3=1+2/3)
2475 Number nr_int(o_number);
2476 nr_int.trunc();
2477 if(isApproximate()) nr_int.setApproximate();
2478 nr_int.print(po2, ips_n);
2479 if(!approximately_displayed || po.base == BASE_ROMAN_NUMERALS || po.base == BASE_BIJECTIVE_26) {
2480 set(nr_int);
2481 MathStructure *mterm;
2482 if(num.isOne()) {
2483 mterm = new MathStructure(den);
2484 mterm->transform(STRUCT_INVERSE);
2485 } else {
2486 mterm = new MathStructure(num);
2487 mterm->transform(STRUCT_DIVISION, den);
2488 }
2489 add_nocopy(mterm);
2490 break;
2491 } else {
2492 approximately_displayed = false;
2493 num = o_number.numerator();
2494 if(isApproximate()) num.setApproximate();
2495 num.print(po2, ips_n);
2496 }
2497 }
2498 if(!approximately_displayed || po.base == BASE_ROMAN_NUMERALS || po.base == BASE_BIJECTIVE_26) {
2499 // both numerator and denominator is displayed exact: split up number
2500 clear(true);
2501 if(num.isOne()) {
2502 m_type = STRUCT_INVERSE;
2503 } else {
2504 m_type = STRUCT_DIVISION;
2505 APPEND_NEW(num);
2506 }
2507 APPEND_NEW(den);
2508 }
2509 }
2510 }
2511 } else if(o_number.hasImaginaryPart()) {
2512 if(o_number.hasRealPart()) {
2513 // split up complex number in real and imaginary part (Z=re(Z)+im(Z)*i)
2514 Number re(o_number.realPart());
2515 Number im(o_number.imaginaryPart());
2516 MathStructure *mstruct = new MathStructure(im);
2517 if(im.isOne()) {
2518 mstruct->set(CALCULATOR->getVariableById(VARIABLE_ID_I));
2519 } else {
2520 mstruct->multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_I)));
2521 if(CALCULATOR->getVariableById(VARIABLE_ID_I)->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg).name == "j") mstruct->swapChildren(1, 2);
2522 }
2523 o_number = re;
2524 add_nocopy(mstruct);
2525 formatsub(po, parent, pindex, true, top_parent);
2526 } else {
2527 // transform imaginary number to imaginary part * i (Z=im(Z)*i)
2528 Number im(o_number.imaginaryPart());
2529 if(im.isOne()) {
2530 set(CALCULATOR->getVariableById(VARIABLE_ID_I), true);
2531 } else if(im.isMinusOne()) {
2532 set(CALCULATOR->getVariableById(VARIABLE_ID_I), true);
2533 transform(STRUCT_NEGATE);
2534 } else {
2535 o_number = im;
2536 multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_I)));
2537 if(CALCULATOR->getVariableById(VARIABLE_ID_I)->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg).name == "j") SWAP_CHILDREN(0, 1);
2538 }
2539 formatsub(po, parent, pindex, true, top_parent);
2540 }
2541 }
2542 break;
2543 }
2544 default: {}
2545 }
2546 }
2547
namelen(const MathStructure & mstruct,const PrintOptions & po,const InternalPrintStruct &,bool * abbreviated=NULL)2548 int namelen(const MathStructure &mstruct, const PrintOptions &po, const InternalPrintStruct&, bool *abbreviated = NULL) {
2549 // returns the length of the name used (for mstruct) with the current mode (and if the name is an abbreviation)
2550 const string *str;
2551 switch(mstruct.type()) {
2552 case STRUCT_FUNCTION: {
2553 const ExpressionName *ename = &mstruct.function()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg);
2554 str = &ename->name;
2555 if(abbreviated) *abbreviated = ename->abbreviation;
2556 break;
2557 }
2558 case STRUCT_VARIABLE: {
2559 const ExpressionName *ename = &mstruct.variable()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg);
2560 str = &ename->name;
2561 if(abbreviated) *abbreviated = ename->abbreviation;
2562 break;
2563 }
2564 case STRUCT_ABORTED: {}
2565 case STRUCT_SYMBOLIC: {
2566 str = &mstruct.symbol();
2567 if(abbreviated) *abbreviated = false;
2568 break;
2569 }
2570 case STRUCT_UNIT: {
2571 const ExpressionName *ename = &mstruct.unit()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, mstruct.isPlural(), po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg);
2572 str = &ename->name;
2573 if(abbreviated) *abbreviated = ename->abbreviation;
2574 break;
2575 }
2576 default: {if(abbreviated) *abbreviated = false; return 0;}
2577 }
2578 if(text_length_is_one(*str)) return 1;
2579 return str->length();
2580 }
2581
needsParenthesis(const PrintOptions & po,const InternalPrintStruct & ips,const MathStructure & parent,size_t index,bool flat_division,bool) const2582 bool MathStructure::needsParenthesis(const PrintOptions &po, const InternalPrintStruct &ips, const MathStructure &parent, size_t index, bool flat_division, bool) const {
2583 // determines, using the type of the parent, the type of the child, the index of the child, and if division is displayed on one line or not (only relevant in the GUI), if this child should be displayed surrounded by parentheses
2584 switch(parent.type()) {
2585 case STRUCT_MULTIPLICATION: {
2586 switch(m_type) {
2587 case STRUCT_MULTIPLICATION: {return po.excessive_parenthesis || (index > 1 && SIZE > 0 && !is_unit_multiexp(*this));}
2588 case STRUCT_DIVISION: {return flat_division && (index < parent.size() || po.excessive_parenthesis);}
2589 case STRUCT_INVERSE: {return flat_division;}
2590 case STRUCT_ADDITION: {return true;}
2591 case STRUCT_POWER: {return po.excessive_parenthesis;}
2592 case STRUCT_NEGATE: {return po.excessive_parenthesis || index > 1 || CHILD(0).needsParenthesis(po, ips, parent, index, flat_division);}
2593 case STRUCT_BITWISE_AND: {return true;}
2594 case STRUCT_BITWISE_OR: {return true;}
2595 case STRUCT_BITWISE_XOR: {return true;}
2596 case STRUCT_BITWISE_NOT: {return po.excessive_parenthesis;}
2597 case STRUCT_LOGICAL_AND: {return true;}
2598 case STRUCT_LOGICAL_OR: {return true;}
2599 case STRUCT_LOGICAL_XOR: {return true;}
2600 case STRUCT_LOGICAL_NOT: {return po.excessive_parenthesis;}
2601 case STRUCT_COMPARISON: {return true;}
2602 case STRUCT_FUNCTION: {return o_function->id() == FUNCTION_ID_UNCERTAINTY;}
2603 case STRUCT_VECTOR: {return false;}
2604 case STRUCT_NUMBER: {return o_number.isInfinite() || (o_number.hasImaginaryPart() && o_number.hasRealPart());}
2605 case STRUCT_VARIABLE: {return false;}
2606 case STRUCT_ABORTED: {return false;}
2607 case STRUCT_SYMBOLIC: {return false;}
2608 case STRUCT_UNIT: {return false;}
2609 case STRUCT_UNDEFINED: {return po.excessive_parenthesis;}
2610 case STRUCT_DATETIME: {return false;}
2611 default: {return true;}
2612 }
2613 }
2614 case STRUCT_INVERSE: {}
2615 case STRUCT_DIVISION: {
2616 switch(m_type) {
2617 case STRUCT_MULTIPLICATION: {return flat_division || po.excessive_parenthesis;}
2618 case STRUCT_DIVISION: {return flat_division || po.excessive_parenthesis;}
2619 case STRUCT_INVERSE: {return flat_division || po.excessive_parenthesis;}
2620 case STRUCT_ADDITION: {return flat_division || po.excessive_parenthesis;}
2621 case STRUCT_POWER: {return flat_division && po.excessive_parenthesis;}
2622 case STRUCT_NEGATE: {return flat_division && po.excessive_parenthesis;}
2623 case STRUCT_BITWISE_AND: {return flat_division || po.excessive_parenthesis;}
2624 case STRUCT_BITWISE_OR: {return flat_division || po.excessive_parenthesis;}
2625 case STRUCT_BITWISE_XOR: {return flat_division || po.excessive_parenthesis;}
2626 case STRUCT_BITWISE_NOT: {return flat_division && po.excessive_parenthesis;}
2627 case STRUCT_LOGICAL_AND: {return flat_division || po.excessive_parenthesis;}
2628 case STRUCT_LOGICAL_OR: {return flat_division || po.excessive_parenthesis;}
2629 case STRUCT_LOGICAL_XOR: {return flat_division || po.excessive_parenthesis;}
2630 case STRUCT_LOGICAL_NOT: {return flat_division && po.excessive_parenthesis;}
2631 case STRUCT_COMPARISON: {return flat_division || po.excessive_parenthesis;}
2632 case STRUCT_FUNCTION: {return o_function->id() == FUNCTION_ID_UNCERTAINTY;}
2633 case STRUCT_VECTOR: {return false;}
2634 case STRUCT_NUMBER: {return (flat_division || po.excessive_parenthesis) && (o_number.isInfinite() || o_number.hasImaginaryPart());}
2635 case STRUCT_VARIABLE: {return false;}
2636 case STRUCT_ABORTED: {return false;}
2637 case STRUCT_SYMBOLIC: {return false;}
2638 case STRUCT_UNIT: {return false;}
2639 case STRUCT_UNDEFINED: {return false;}
2640 case STRUCT_DATETIME: {return false;}
2641 default: {return true;}
2642 }
2643 }
2644 case STRUCT_ADDITION: {
2645 switch(m_type) {
2646 case STRUCT_MULTIPLICATION: {return po.excessive_parenthesis;}
2647 case STRUCT_DIVISION: {return flat_division && po.excessive_parenthesis;}
2648 case STRUCT_INVERSE: {return flat_division && po.excessive_parenthesis;}
2649 case STRUCT_ADDITION: {return true;}
2650 case STRUCT_POWER: {return po.excessive_parenthesis;}
2651 case STRUCT_NEGATE: {return index > 1 || po.excessive_parenthesis;}
2652 case STRUCT_BITWISE_AND: {return true;}
2653 case STRUCT_BITWISE_OR: {return true;}
2654 case STRUCT_BITWISE_XOR: {return true;}
2655 case STRUCT_BITWISE_NOT: {return false;}
2656 case STRUCT_LOGICAL_AND: {return true;}
2657 case STRUCT_LOGICAL_OR: {return true;}
2658 case STRUCT_LOGICAL_XOR: {return true;}
2659 case STRUCT_LOGICAL_NOT: {return false;}
2660 case STRUCT_COMPARISON: {return true;}
2661 case STRUCT_FUNCTION: {return false;}
2662 case STRUCT_VECTOR: {return false;}
2663 case STRUCT_NUMBER: {return o_number.isInfinite();}
2664 case STRUCT_VARIABLE: {return false;}
2665 case STRUCT_ABORTED: {return false;}
2666 case STRUCT_SYMBOLIC: {return false;}
2667 case STRUCT_UNIT: {return false;}
2668 case STRUCT_UNDEFINED: {return false;}
2669 case STRUCT_DATETIME: {return false;}
2670 default: {return true;}
2671 }
2672 }
2673 case STRUCT_POWER: {
2674 switch(m_type) {
2675 case STRUCT_MULTIPLICATION: {return true;}
2676 case STRUCT_DIVISION: {return index == 1 || flat_division || po.excessive_parenthesis;}
2677 case STRUCT_INVERSE: {return index == 1 || flat_division || po.excessive_parenthesis;}
2678 case STRUCT_ADDITION: {return true;}
2679 case STRUCT_POWER: {return true;}
2680 case STRUCT_NEGATE: {return index == 1 || CHILD(0).needsParenthesis(po, ips, parent, index, flat_division);}
2681 case STRUCT_BITWISE_AND: {return true;}
2682 case STRUCT_BITWISE_OR: {return true;}
2683 case STRUCT_BITWISE_XOR: {return true;}
2684 case STRUCT_BITWISE_NOT: {return index == 1 || po.excessive_parenthesis;}
2685 case STRUCT_LOGICAL_AND: {return true;}
2686 case STRUCT_LOGICAL_OR: {return true;}
2687 case STRUCT_LOGICAL_XOR: {return true;}
2688 case STRUCT_LOGICAL_NOT: {return index == 1 || po.excessive_parenthesis;}
2689 case STRUCT_COMPARISON: {return true;}
2690 case STRUCT_FUNCTION: {return o_function->id() == FUNCTION_ID_UNCERTAINTY;}
2691 case STRUCT_VECTOR: {return false;}
2692 case STRUCT_NUMBER: {return o_number.isInfinite() || o_number.hasImaginaryPart();}
2693 case STRUCT_VARIABLE: {return false;}
2694 case STRUCT_ABORTED: {return false;}
2695 case STRUCT_SYMBOLIC: {return false;}
2696 case STRUCT_UNIT: {return false;}
2697 case STRUCT_UNDEFINED: {return false;}
2698 default: {return true;}
2699 }
2700 }
2701 case STRUCT_NEGATE: {
2702 switch(m_type) {
2703 case STRUCT_MULTIPLICATION: {return po.excessive_parenthesis;}
2704 case STRUCT_DIVISION: {return po.excessive_parenthesis;}
2705 case STRUCT_INVERSE: {return flat_division && po.excessive_parenthesis;}
2706 case STRUCT_ADDITION: {return true;}
2707 case STRUCT_POWER: {return po.excessive_parenthesis;}
2708 case STRUCT_NEGATE: {return true;}
2709 case STRUCT_BITWISE_AND: {return true;}
2710 case STRUCT_BITWISE_OR: {return true;}
2711 case STRUCT_BITWISE_XOR: {return true;}
2712 case STRUCT_BITWISE_NOT: {return po.excessive_parenthesis;}
2713 case STRUCT_LOGICAL_AND: {return true;}
2714 case STRUCT_LOGICAL_OR: {return true;}
2715 case STRUCT_LOGICAL_XOR: {return true;}
2716 case STRUCT_LOGICAL_NOT: {return po.excessive_parenthesis;}
2717 case STRUCT_COMPARISON: {return true;}
2718 case STRUCT_FUNCTION: {return false;}
2719 case STRUCT_VECTOR: {return false;}
2720 case STRUCT_NUMBER: {return o_number.isInfinite() || (o_number.hasImaginaryPart() && o_number.hasRealPart());}
2721 case STRUCT_VARIABLE: {return false;}
2722 case STRUCT_ABORTED: {return false;}
2723 case STRUCT_SYMBOLIC: {return false;}
2724 case STRUCT_UNIT: {return false;}
2725 case STRUCT_UNDEFINED: {return false;}
2726 default: {return true;}
2727 }
2728 }
2729 case STRUCT_LOGICAL_OR: {}
2730 case STRUCT_LOGICAL_AND: {}
2731 case STRUCT_LOGICAL_XOR: {
2732 switch(m_type) {
2733 case STRUCT_MULTIPLICATION: {return true;}
2734 case STRUCT_DIVISION: {return flat_division;}
2735 case STRUCT_INVERSE: {return flat_division;}
2736 case STRUCT_ADDITION: {return true;}
2737 case STRUCT_POWER: {return po.excessive_parenthesis;}
2738 case STRUCT_NEGATE: {return po.excessive_parenthesis;}
2739 case STRUCT_BITWISE_AND: {return true;}
2740 case STRUCT_BITWISE_OR: {return true;}
2741 case STRUCT_BITWISE_XOR: {return true;}
2742 case STRUCT_BITWISE_NOT: {return false;}
2743 case STRUCT_LOGICAL_AND: {return true;}
2744 case STRUCT_LOGICAL_OR: {return true;}
2745 case STRUCT_LOGICAL_XOR: {return true;}
2746 case STRUCT_LOGICAL_NOT: {return false;}
2747 case STRUCT_COMPARISON: {return false;}
2748 case STRUCT_FUNCTION: {return false;}
2749 case STRUCT_VECTOR: {return false;}
2750 case STRUCT_NUMBER: {return po.excessive_parenthesis && o_number.isInfinite();}
2751 case STRUCT_VARIABLE: {return false;}
2752 case STRUCT_ABORTED: {return false;}
2753 case STRUCT_SYMBOLIC: {return false;}
2754 case STRUCT_UNIT: {return false;}
2755 case STRUCT_UNDEFINED: {return false;}
2756 case STRUCT_DATETIME: {return false;}
2757 default: {return true;}
2758 }
2759 }
2760 case STRUCT_BITWISE_AND: {}
2761 case STRUCT_BITWISE_OR: {}
2762 case STRUCT_BITWISE_XOR: {
2763 switch(m_type) {
2764 case STRUCT_MULTIPLICATION: {return true;}
2765 case STRUCT_DIVISION: {return flat_division;}
2766 case STRUCT_INVERSE: {return flat_division;}
2767 case STRUCT_ADDITION: {return true;}
2768 case STRUCT_POWER: {return po.excessive_parenthesis;}
2769 case STRUCT_NEGATE: {return po.excessive_parenthesis;}
2770 case STRUCT_BITWISE_AND: {return true;}
2771 case STRUCT_BITWISE_OR: {return true;}
2772 case STRUCT_BITWISE_XOR: {return true;}
2773 case STRUCT_BITWISE_NOT: {return false;}
2774 case STRUCT_LOGICAL_AND: {return true;}
2775 case STRUCT_LOGICAL_OR: {return true;}
2776 case STRUCT_LOGICAL_XOR: {return true;}
2777 case STRUCT_LOGICAL_NOT: {return false;}
2778 case STRUCT_COMPARISON: {return true;}
2779 case STRUCT_FUNCTION: {return false;}
2780 case STRUCT_VECTOR: {return false;}
2781 case STRUCT_NUMBER: {return po.excessive_parenthesis && o_number.isInfinite();}
2782 case STRUCT_VARIABLE: {return false;}
2783 case STRUCT_ABORTED: {return false;}
2784 case STRUCT_SYMBOLIC: {return false;}
2785 case STRUCT_UNIT: {return false;}
2786 case STRUCT_UNDEFINED: {return false;}
2787 default: {return true;}
2788 }
2789 }
2790 case STRUCT_COMPARISON: {
2791 switch(m_type) {
2792 case STRUCT_MULTIPLICATION: {return po.excessive_parenthesis;}
2793 case STRUCT_DIVISION: {return flat_division && po.excessive_parenthesis;}
2794 case STRUCT_INVERSE: {return flat_division && po.excessive_parenthesis;}
2795 case STRUCT_ADDITION: {return po.excessive_parenthesis;}
2796 case STRUCT_POWER: {return po.excessive_parenthesis;}
2797 case STRUCT_NEGATE: {return po.excessive_parenthesis;}
2798 case STRUCT_BITWISE_AND: {return true;}
2799 case STRUCT_BITWISE_OR: {return true;}
2800 case STRUCT_BITWISE_XOR: {return true;}
2801 case STRUCT_BITWISE_NOT: {return false;}
2802 case STRUCT_LOGICAL_AND: {return true;}
2803 case STRUCT_LOGICAL_OR: {return true;}
2804 case STRUCT_LOGICAL_XOR: {return true;}
2805 case STRUCT_LOGICAL_NOT: {return false;}
2806 case STRUCT_COMPARISON: {return true;}
2807 case STRUCT_FUNCTION: {return false;}
2808 case STRUCT_VECTOR: {return false;}
2809 case STRUCT_NUMBER: {return po.excessive_parenthesis && o_number.isInfinite();}
2810 case STRUCT_VARIABLE: {return false;}
2811 case STRUCT_ABORTED: {return false;}
2812 case STRUCT_SYMBOLIC: {return false;}
2813 case STRUCT_UNIT: {return false;}
2814 case STRUCT_UNDEFINED: {return false;}
2815 case STRUCT_DATETIME: {return false;}
2816 default: {return true;}
2817 }
2818 }
2819 case STRUCT_LOGICAL_NOT: {}
2820 case STRUCT_BITWISE_NOT: {
2821 switch(m_type) {
2822 case STRUCT_MULTIPLICATION: {return true;}
2823 case STRUCT_DIVISION: {return true;}
2824 case STRUCT_INVERSE: {return true;}
2825 case STRUCT_ADDITION: {return true;}
2826 case STRUCT_POWER: {return po.excessive_parenthesis;}
2827 case STRUCT_NEGATE: {return po.excessive_parenthesis;}
2828 case STRUCT_BITWISE_AND: {return true;}
2829 case STRUCT_BITWISE_OR: {return true;}
2830 case STRUCT_BITWISE_XOR: {return true;}
2831 case STRUCT_BITWISE_NOT: {return true;}
2832 case STRUCT_LOGICAL_AND: {return true;}
2833 case STRUCT_LOGICAL_OR: {return true;}
2834 case STRUCT_LOGICAL_XOR: {return true;}
2835 case STRUCT_LOGICAL_NOT: {return true;}
2836 case STRUCT_COMPARISON: {return true;}
2837 case STRUCT_FUNCTION: {return po.excessive_parenthesis;}
2838 case STRUCT_VECTOR: {return po.excessive_parenthesis;}
2839 case STRUCT_NUMBER: {return po.excessive_parenthesis;}
2840 case STRUCT_VARIABLE: {return po.excessive_parenthesis;}
2841 case STRUCT_ABORTED: {return po.excessive_parenthesis;}
2842 case STRUCT_SYMBOLIC: {return po.excessive_parenthesis;}
2843 case STRUCT_UNIT: {return po.excessive_parenthesis;}
2844 case STRUCT_UNDEFINED: {return po.excessive_parenthesis;}
2845 default: {return true;}
2846 }
2847 }
2848 case STRUCT_FUNCTION: {
2849 return false;
2850 }
2851 case STRUCT_VECTOR: {
2852 return false;
2853 }
2854 default: {
2855 return true;
2856 }
2857 }
2858 }
2859
neededMultiplicationSign(const PrintOptions & po,const InternalPrintStruct & ips,const MathStructure & parent,size_t index,bool par,bool par_prev,bool flat_division,bool flat_power) const2860 int MathStructure::neededMultiplicationSign(const PrintOptions &po, const InternalPrintStruct &ips, const MathStructure &parent, size_t index, bool par, bool par_prev, bool flat_division, bool flat_power) const {
2861 // returns the suggested multiplication sign in front of this MathStrcture
2862
2863 // do not display anything on front of the first factor (this function is normally not called in this case)
2864 if(index <= 1) return MULTIPLICATION_SIGN_NONE;
2865 // short multiplication is disabled or number base might use digits other than 0-9, alawys show multiplication symbol
2866 if(!po.short_multiplication || po.base > 10 || po.base < 2) return MULTIPLICATION_SIGN_OPERATOR;
2867 // no multiplication sign between factors in parentheses
2868 if(par_prev && par) return MULTIPLICATION_SIGN_NONE;
2869 if(par_prev) {
2870 // (a)*u=(a) u
2871 if(is_unit_multiexp(*this)) return MULTIPLICATION_SIGN_SPACE;
2872 if(isUnknown_exp()) {
2873 // (a)*"xy"=(a) "xy", (a)*"xy"^b=(a) "xy"^b, (a)*x=(a)x, (a)*x^b=ax^b
2874 return (namelen(isPower() ? CHILD(0) : *this, po, ips, NULL) > 1 ? MULTIPLICATION_SIGN_SPACE : MULTIPLICATION_SIGN_NONE);
2875 }
2876 if(isMultiplication() && SIZE > 0) {
2877 // (a)*uv=(a) uv
2878 if(CHILD(0).isUnit_exp()) return MULTIPLICATION_SIGN_SPACE;
2879 if(CHILD(0).isUnknown_exp()) {
2880 // (a)*"xy"z=(a) "xy"z, (a)*xy=(a)xy
2881 return (namelen(CHILD(0).isPower() ? CHILD(0)[0] : CHILD(0), po, ips, NULL) > 1 ? MULTIPLICATION_SIGN_SPACE : MULTIPLICATION_SIGN_NONE);
2882 }
2883 } else if(isDivision()) {
2884 // (a)*(u1/u2)=(a) u1/u2
2885 for(size_t i = 0; i < SIZE; i++) {
2886 if(!CHILD(i).isUnit_exp()) {
2887 return MULTIPLICATION_SIGN_OPERATOR;
2888 }
2889 }
2890 return MULTIPLICATION_SIGN_SPACE;
2891 }
2892 // (a)*bc
2893 return MULTIPLICATION_SIGN_OPERATOR;
2894 }
2895 // type of factor in front in this factor
2896 int t = parent[index - 2].type();
2897 // a^b*c (if b is not shown using superscript or similar)
2898 if(flat_power && t == STRUCT_POWER) {
2899 if(!po.place_units_separately || !parent[index - 2].isUnit_exp()) return MULTIPLICATION_SIGN_OPERATOR;
2900 }
2901 // a^b*(c)=a^b (c)
2902 if(par && t == STRUCT_POWER) return MULTIPLICATION_SIGN_SPACE;
2903 // a*(b)=a(b)
2904 if(par) return MULTIPLICATION_SIGN_NONE;
2905 // check if involved names have only one character
2906 bool abbr_prev = false, abbr_this = false;
2907 int namelen_this = namelen(*this, po, ips, &abbr_this);
2908 int namelen_prev = namelen(parent[index - 2], po, ips, &abbr_prev);
2909 switch(t) {
2910 case STRUCT_MULTIPLICATION: {break;}
2911 case STRUCT_INVERSE: {}
2912 case STRUCT_DIVISION: {if(flat_division) return MULTIPLICATION_SIGN_OPERATOR; return MULTIPLICATION_SIGN_SPACE;}
2913 case STRUCT_ADDITION: {return MULTIPLICATION_SIGN_OPERATOR;}
2914 case STRUCT_POWER: {
2915 if(m_type == STRUCT_UNIT && parent[index - 2][0].isUnit()) {
2916 namelen(parent[index - 2], po, ips, &abbr_prev);
2917 if(po.place_units_separately) return MULTIPLICATION_SIGN_OPERATOR_SHORT;
2918 else if(!flat_power && !po.limit_implicit_multiplication && !abbr_prev && !abbr_this) return MULTIPLICATION_SIGN_SPACE;
2919 else return MULTIPLICATION_SIGN_OPERATOR;
2920 }
2921 break;
2922 }
2923 case STRUCT_NEGATE: {break;}
2924 case STRUCT_BITWISE_AND: {return MULTIPLICATION_SIGN_OPERATOR;}
2925 case STRUCT_BITWISE_OR: {return MULTIPLICATION_SIGN_OPERATOR;}
2926 case STRUCT_BITWISE_XOR: {return MULTIPLICATION_SIGN_OPERATOR;}
2927 case STRUCT_BITWISE_NOT: {return MULTIPLICATION_SIGN_OPERATOR;}
2928 case STRUCT_LOGICAL_AND: {return MULTIPLICATION_SIGN_OPERATOR;}
2929 case STRUCT_LOGICAL_OR: {return MULTIPLICATION_SIGN_OPERATOR;}
2930 case STRUCT_LOGICAL_XOR: {return MULTIPLICATION_SIGN_OPERATOR;}
2931 case STRUCT_LOGICAL_NOT: {return MULTIPLICATION_SIGN_OPERATOR;}
2932 case STRUCT_COMPARISON: {return MULTIPLICATION_SIGN_OPERATOR;}
2933 case STRUCT_FUNCTION: {return MULTIPLICATION_SIGN_OPERATOR;}
2934 case STRUCT_VECTOR: {break;}
2935 case STRUCT_NUMBER: {break;}
2936 case STRUCT_VARIABLE: {break;}
2937 case STRUCT_ABORTED: {break;}
2938 case STRUCT_SYMBOLIC: {break;}
2939 case STRUCT_UNIT: {
2940 if(m_type == STRUCT_UNIT) {
2941 if(po.place_units_separately) {
2942 return MULTIPLICATION_SIGN_OPERATOR_SHORT;
2943 } else if(!po.limit_implicit_multiplication && !abbr_prev && !abbr_this) {
2944 return MULTIPLICATION_SIGN_SPACE;
2945 } else {
2946 return MULTIPLICATION_SIGN_OPERATOR;
2947 }
2948 } else if(m_type == STRUCT_NUMBER) {
2949 if(namelen_prev > 1) {
2950 return MULTIPLICATION_SIGN_SPACE;
2951 } else {
2952 return MULTIPLICATION_SIGN_NONE;
2953 }
2954 }
2955 //return MULTIPLICATION_SIGN_SPACE;
2956 }
2957 case STRUCT_UNDEFINED: {break;}
2958 default: {return MULTIPLICATION_SIGN_OPERATOR;}
2959 }
2960 switch(m_type) {
2961 case STRUCT_MULTIPLICATION: {if(SIZE > 0) {return CHILD(0).neededMultiplicationSign(po, ips, parent, index, par, par_prev, flat_division, flat_power);} return MULTIPLICATION_SIGN_OPERATOR;}
2962 case STRUCT_INVERSE: {if(flat_division) {return m_one.neededMultiplicationSign(po, ips, parent, index, par, par_prev, flat_division, flat_power);} return MULTIPLICATION_SIGN_SPACE;}
2963 case STRUCT_DIVISION: {if(flat_division) {return CHILD(0).neededMultiplicationSign(po, ips, parent, index, par, par_prev, flat_division, flat_power);} return MULTIPLICATION_SIGN_SPACE;}
2964 case STRUCT_ADDITION: {return MULTIPLICATION_SIGN_OPERATOR;}
2965 case STRUCT_POWER: {return CHILD(0).neededMultiplicationSign(po, ips, parent, index, par, par_prev, flat_division, flat_power);}
2966 case STRUCT_NEGATE: {return MULTIPLICATION_SIGN_OPERATOR;}
2967 case STRUCT_BITWISE_AND: {return MULTIPLICATION_SIGN_OPERATOR;}
2968 case STRUCT_BITWISE_OR: {return MULTIPLICATION_SIGN_OPERATOR;}
2969 case STRUCT_BITWISE_XOR: {return MULTIPLICATION_SIGN_OPERATOR;}
2970 case STRUCT_BITWISE_NOT: {return MULTIPLICATION_SIGN_OPERATOR;}
2971 case STRUCT_LOGICAL_AND: {return MULTIPLICATION_SIGN_OPERATOR;}
2972 case STRUCT_LOGICAL_OR: {return MULTIPLICATION_SIGN_OPERATOR;}
2973 case STRUCT_LOGICAL_XOR: {return MULTIPLICATION_SIGN_OPERATOR;}
2974 case STRUCT_LOGICAL_NOT: {return MULTIPLICATION_SIGN_OPERATOR;}
2975 case STRUCT_COMPARISON: {return MULTIPLICATION_SIGN_OPERATOR;}
2976 case STRUCT_FUNCTION: {return MULTIPLICATION_SIGN_OPERATOR;}
2977 case STRUCT_VECTOR: {return MULTIPLICATION_SIGN_OPERATOR;}
2978 case STRUCT_NUMBER: {
2979 if(t == STRUCT_VARIABLE && parent[index - 2].variable() == CALCULATOR->getVariableById(VARIABLE_ID_I)) return MULTIPLICATION_SIGN_NONE;
2980 return MULTIPLICATION_SIGN_OPERATOR;
2981 }
2982 case STRUCT_VARIABLE: {
2983 if(!o_variable->isRegistered() && o_variable->getName(1).name.length() > 0 && o_variable->getName(1).name[0] >= '0' && o_variable->getName(1).name[0] <= '9') return MULTIPLICATION_SIGN_OPERATOR;
2984 }
2985 case STRUCT_ABORTED: {}
2986 case STRUCT_SYMBOLIC: {
2987 if(po.limit_implicit_multiplication && t != STRUCT_NUMBER) return MULTIPLICATION_SIGN_OPERATOR;
2988 if(t != STRUCT_NUMBER && ((namelen_prev > 1 || namelen_this > 1) || equals(parent[index - 2]))) return MULTIPLICATION_SIGN_OPERATOR;
2989 if(namelen_this > 1) return MULTIPLICATION_SIGN_SPACE;
2990 return MULTIPLICATION_SIGN_NONE;
2991 }
2992 case STRUCT_UNIT: {
2993 if(o_unit == CALCULATOR->getDegUnit() && print(po) == SIGN_DEGREE) {
2994 return MULTIPLICATION_SIGN_NONE;
2995 }
2996 return MULTIPLICATION_SIGN_SPACE;
2997 }
2998 case STRUCT_UNDEFINED: {return MULTIPLICATION_SIGN_OPERATOR;}
2999 default: {return MULTIPLICATION_SIGN_OPERATOR;}
3000 }
3001 }
3002
operator <<(ostream & os,const MathStructure & mstruct)3003 ostream& operator << (ostream &os, const MathStructure &mstruct) {
3004 os << format_and_print(mstruct);
3005 return os;
3006 }
print(const PrintOptions & po,const InternalPrintStruct & ips) const3007 string MathStructure::print(const PrintOptions &po, const InternalPrintStruct &ips) const {
3008 return print(po, false, 0, TAG_TYPE_HTML, ips);
3009 }
print(const PrintOptions & po,bool format,int colorize,int tagtype,const InternalPrintStruct & ips) const3010 string MathStructure::print(const PrintOptions &po, bool format, int colorize, int tagtype, const InternalPrintStruct &ips) const {
3011 if(ips.depth == 0 && po.is_approximate) *po.is_approximate = false;
3012 string print_str;
3013 InternalPrintStruct ips_n = ips;
3014 if(isApproximate()) ips_n.parent_approximate = true;
3015 if(precision() >= 0 && (ips_n.parent_precision < 0 || precision() < ips_n.parent_precision)) ips_n.parent_precision = precision();
3016 switch(m_type) {
3017 case STRUCT_NUMBER: {
3018 if(colorize && tagtype == TAG_TYPE_TERMINAL) print_str = (colorize == 2 ? "\033[0;96m" : "\033[0;36m");
3019 print_str += o_number.print(po, ips_n);
3020 if(colorize && tagtype == TAG_TYPE_TERMINAL) print_str += "\033[0m";
3021 break;
3022 }
3023 case STRUCT_ABORTED: {}
3024 case STRUCT_SYMBOLIC: {
3025 if(po.allow_non_usable) {
3026 print_str = s_sym;
3027 } else {
3028 if((text_length_is_one(s_sym) && s_sym.find("\'") == string::npos) || s_sym.find("\"") != string::npos) {
3029 print_str = "\'";
3030 print_str += s_sym;
3031 print_str += "\'";
3032 } else {
3033 print_str = "\"";
3034 print_str += s_sym;
3035 print_str += "\"";
3036 }
3037 }
3038 if((format && m_type != STRUCT_ABORTED) || (colorize && tagtype == TAG_TYPE_TERMINAL)) {
3039 if(tagtype == TAG_TYPE_TERMINAL) {
3040 if(format) print_str.insert(0, "\033[3m");
3041 if(colorize && m_type == STRUCT_ABORTED) print_str.insert(0, colorize == 2 ? "\033[0;91m" : "\033[0;31m");
3042 else if(colorize) print_str.insert(0, colorize == 2 ? "\033[0;93m" : "\033[0;33m");
3043 if(format) print_str += "\033[23m";
3044 if(colorize) print_str += "\033[0m";
3045 } else {
3046 print_str.insert(0, "<i>");
3047 print_str += "</i>";
3048 }
3049 }
3050 break;
3051 }
3052 case STRUCT_DATETIME: {
3053 if(colorize && tagtype == TAG_TYPE_TERMINAL) print_str = (colorize == 2 ? "\033[0;96m" : "\033[0;36m");
3054 print_str += "\"";
3055 print_str += o_datetime->print(po);
3056 print_str += "\"";
3057 if(colorize && tagtype == TAG_TYPE_TERMINAL) print_str += "\033[0m";
3058 break;
3059 }
3060 case STRUCT_ADDITION: {
3061 ips_n.depth++;
3062 for(size_t i = 0; i < SIZE; i++) {
3063 if(CALCULATOR->aborted()) return CALCULATOR->abortedMessage();
3064 if(i > 0) {
3065 if(CHILD(i).type() == STRUCT_NEGATE) {
3066 if(po.spacious) print_str += " ";
3067 if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MINUS, po.can_display_unicode_string_arg))) print_str += SIGN_MINUS;
3068 else print_str += "-";
3069 if(po.spacious) print_str += " ";
3070 ips_n.wrap = CHILD(i)[0].needsParenthesis(po, ips_n, *this, i + 1, true, true);
3071 print_str += CHILD(i)[0].print(po, format, colorize, tagtype, ips_n);
3072 } else {
3073 if(po.spacious) print_str += " ";
3074 print_str += "+";
3075 if(po.spacious) print_str += " ";
3076 ips_n.wrap = CHILD(i).needsParenthesis(po, ips_n, *this, i + 1, true, true);
3077 print_str += CHILD(i).print(po, format, colorize, tagtype, ips_n);
3078 }
3079 } else {
3080 ips_n.wrap = CHILD(i).needsParenthesis(po, ips_n, *this, i + 1, true, true);
3081 print_str += CHILD(i).print(po, format, colorize, tagtype, ips_n);
3082 }
3083 }
3084 break;
3085 }
3086 case STRUCT_NEGATE: {
3087 ips_n.wrap = CHILD(0).needsParenthesis(po, ips_n, *this, 1, true, true);
3088 bool b_num = !po.preserve_format && colorize && tagtype == TAG_TYPE_TERMINAL && !ips_n.wrap && (CHILD(0).isNumber() || (CHILD(0).isDivision() && CHILD(0)[0].isNumber()) || CHILD(0).isInverse() || (CHILD(0).isMultiplication() && CHILD(0).size() > 0 && CHILD(0)[0].isNumber()));
3089 if(b_num) print_str += (colorize == 2 ? "\033[0;96m" : "\033[0;36m");
3090 if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MINUS, po.can_display_unicode_string_arg))) print_str += SIGN_MINUS;
3091 else print_str += "-";
3092 if(b_num) print_str += "\033[0m";
3093 ips_n.depth++;
3094 print_str += CHILD(0).print(po, format, colorize, tagtype, ips_n);
3095 break;
3096 }
3097 case STRUCT_MULTIPLICATION: {
3098 ips_n.depth++;
3099 if(!po.preserve_format && SIZE == 2 && (CHILD(0).isNumber() || (CHILD(0).isNegate() && CHILD(0)[0].isNumber())) && CHILD(1).isFunction() && CHILD(1).size() == 1 && CHILD(1).function()->id() == FUNCTION_ID_CIS && CHILD(1).function()->referenceName() == "cis") {
3100 ips_n.wrap = false;
3101 print_str += CHILD(0).print(po, format, colorize, tagtype, ips_n);
3102 print_str += " ";
3103 print_str += "cis";
3104 print_str += " ";
3105 ips_n.wrap = (CHILD(1)[0].size() > 0 && (!CHILD(1)[0].isMultiplication() || CHILD(1)[0].size() != 2 || CHILD(1)[0][1].neededMultiplicationSign(po, ips_n, CHILD(1)[0], 2, false, false, false, false) != MULTIPLICATION_SIGN_NONE) && (!CHILD(1)[0].isNegate() || (CHILD(1)[0][0].size() > 0 && (!CHILD(1)[0][0].isMultiplication() || CHILD(1)[0][0][1].neededMultiplicationSign(po, ips_n, CHILD(1)[0][0], 2, false, false, false, false) != MULTIPLICATION_SIGN_NONE))));
3106 print_str += CHILD(1)[0].print(po, format, colorize, tagtype, ips_n);
3107 break;
3108 }
3109 bool b_units = false;
3110 bool par_prev = false;
3111 for(size_t i = 0; i < SIZE; i++) {
3112 if(CALCULATOR->aborted()) return CALCULATOR->abortedMessage();
3113 ips_n.wrap = CHILD(i).needsParenthesis(po, ips_n, *this, i + 1, true, true);
3114 if(!po.short_multiplication && i > 0) {
3115 if(po.spacious) print_str += " ";
3116 if(po.use_unicode_signs && po.multiplication_sign == MULTIPLICATION_SIGN_DOT && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MULTIDOT, po.can_display_unicode_string_arg))) print_str += SIGN_MULTIDOT;
3117 else if(po.use_unicode_signs && (po.multiplication_sign == MULTIPLICATION_SIGN_DOT || po.multiplication_sign == MULTIPLICATION_SIGN_ALTDOT) && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MIDDLEDOT, po.can_display_unicode_string_arg))) print_str += SIGN_MIDDLEDOT;
3118 else if(po.use_unicode_signs && po.multiplication_sign == MULTIPLICATION_SIGN_X && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MULTIPLICATION, po.can_display_unicode_string_arg))) print_str += SIGN_MULTIPLICATION;
3119 else print_str += "*";
3120 if(po.spacious) print_str += " ";
3121 } else if(i > 0) {
3122 int i_sign = CHILD(i).neededMultiplicationSign(po, ips_n, *this, i + 1, ips_n.wrap || (CHILD(i).isPower() && CHILD(i)[0].needsParenthesis(po, ips_n, CHILD(i), 1, true, true)), par_prev, true, true);
3123 if(i_sign == MULTIPLICATION_SIGN_NONE && CHILD(i).isPower() && CHILD(i)[0].isUnit() && po.use_unicode_signs && po.abbreviate_names && CHILD(i)[0].unit() == CALCULATOR->getDegUnit()) {
3124 PrintOptions po2 = po;
3125 po2.use_unicode_signs = false;
3126 i_sign = CHILD(i).neededMultiplicationSign(po2, ips_n, *this, i + 1, ips_n.wrap || (CHILD(i).isPower() && CHILD(i)[0].needsParenthesis(po, ips_n, CHILD(i), 1, true, true)), par_prev, true, true);
3127 }
3128 switch(i_sign) {
3129 case MULTIPLICATION_SIGN_SPACE: {print_str += " "; break;}
3130 case MULTIPLICATION_SIGN_OPERATOR: {
3131 if(po.spacious) {
3132 if(po.use_unicode_signs && po.multiplication_sign == MULTIPLICATION_SIGN_DOT && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MULTIDOT, po.can_display_unicode_string_arg))) print_str += " " SIGN_MULTIDOT " ";
3133 else if(po.use_unicode_signs && (po.multiplication_sign == MULTIPLICATION_SIGN_DOT || po.multiplication_sign == MULTIPLICATION_SIGN_ALTDOT) && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MIDDLEDOT, po.can_display_unicode_string_arg))) print_str += " " SIGN_MIDDLEDOT " ";
3134 else if(po.use_unicode_signs && po.multiplication_sign == MULTIPLICATION_SIGN_X && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MULTIPLICATION, po.can_display_unicode_string_arg))) print_str += " " SIGN_MULTIPLICATION " ";
3135 else print_str += " * ";
3136 break;
3137 }
3138 }
3139 case MULTIPLICATION_SIGN_OPERATOR_SHORT: {
3140 if(po.use_unicode_signs && po.multiplication_sign == MULTIPLICATION_SIGN_DOT && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MULTIDOT, po.can_display_unicode_string_arg))) print_str += SIGN_MULTIDOT;
3141 else if(po.use_unicode_signs && (po.multiplication_sign == MULTIPLICATION_SIGN_DOT || po.multiplication_sign == MULTIPLICATION_SIGN_ALTDOT || (po.place_units_separately && po.multiplication_sign == MULTIPLICATION_SIGN_X && CHILD(i).isUnit_exp() && CHILD(i - 1).isUnit_exp())) && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MIDDLEDOT, po.can_display_unicode_string_arg))) print_str += SIGN_MIDDLEDOT;
3142 else if(po.use_unicode_signs && po.multiplication_sign == MULTIPLICATION_SIGN_X && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MULTIPLICATION, po.can_display_unicode_string_arg))) print_str += SIGN_MULTIPLICATION;
3143 else print_str += "*";
3144 break;
3145 }
3146 }
3147 }
3148 if(!b_units && po.place_units_separately && !po.preserve_format && colorize && tagtype == TAG_TYPE_TERMINAL) {
3149 b_units = true;
3150 for(size_t i2 = i; i2 < SIZE; i2++) {
3151 if(!CHILD(i2).isUnit_exp()) {
3152 b_units = false;
3153 break;
3154 }
3155 }
3156 if(b_units) print_str += (colorize == 2 ? "\033[0;92m" : "\033[0;32m");
3157 }
3158 print_str += CHILD(i).print(po, format, b_units ? 0 : colorize, tagtype, ips_n);
3159 par_prev = ips_n.wrap;
3160 }
3161 if(b_units) print_str += "\033[0m";
3162 break;
3163 }
3164 case STRUCT_INVERSE: {
3165 ips_n.depth++;
3166 ips_n.division_depth++;
3167 ips_n.wrap = false;
3168 bool b_num = !po.preserve_format && po.division_sign == DIVISION_SIGN_SLASH && CHILD(0).isInteger();
3169 if(b_num && colorize && tagtype == TAG_TYPE_TERMINAL) print_str += (colorize == 2 ? "\033[0;96m" : "\033[0;36m");
3170 print_str += m_one.print(po, !b_num && format, b_num ? 0 : colorize, tagtype, ips_n);
3171 if(po.use_unicode_signs && po.division_sign == DIVISION_SIGN_DIVISION && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_DIVISION, po.can_display_unicode_string_arg))) {
3172 if(po.spacious && !b_num) print_str += " ";
3173 print_str += SIGN_DIVISION;
3174 if(po.spacious && !b_num) print_str += " ";
3175 } else if(po.use_unicode_signs && po.division_sign == DIVISION_SIGN_DIVISION_SLASH && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_DIVISION_SLASH, po.can_display_unicode_string_arg))) {
3176 print_str += " " SIGN_DIVISION_SLASH " ";
3177 } else {
3178 if(po.spacious && !b_num) print_str += " ";
3179 print_str += "/";
3180 if(po.spacious && !b_num) print_str += " ";
3181 }
3182 if(b_num && (po.number_fraction_format == FRACTION_DECIMAL || po.number_fraction_format == FRACTION_DECIMAL_EXACT)) {
3183 PrintOptions po2 = po;
3184 po2.number_fraction_format = FRACTION_FRACTIONAL;
3185 ips_n.wrap = CHILD(0).needsParenthesis(po, ips_n, *this, 1, true, true);
3186 print_str += CHILD(0).print(po, false, 0, tagtype, ips_n);
3187 } else {
3188 ips_n.wrap = CHILD(0).needsParenthesis(po, ips_n, *this, 1, true, true);
3189 print_str += CHILD(0).print(po, !b_num && format, b_num ? 0 : colorize, tagtype, ips_n);
3190 }
3191 if(b_num && colorize && tagtype == TAG_TYPE_TERMINAL) print_str += "\033[0m";
3192 break;
3193 }
3194 case STRUCT_DIVISION: {
3195 ips_n.depth++;
3196 ips_n.division_depth++;
3197 bool b_num = !po.preserve_format && CHILD(0).isInteger() && CHILD(1).isInteger();
3198 bool b_num2 = b_num && po.division_sign == DIVISION_SIGN_SLASH;
3199 bool b_units = false;
3200 if(!b_num && po.place_units_separately && !po.preserve_format) {
3201 b_units = true;
3202 if(CHILD(0).isMultiplication()) {
3203 for(size_t i2 = 0; i2 < CHILD(0).size(); i2++) {
3204 if(!CHILD(0)[i2].isUnit_exp()) {
3205 b_units = false;
3206 break;
3207 }
3208 }
3209 } else if(!CHILD(0).isUnit_exp()) {
3210 b_units = false;
3211 }
3212 if(b_units) {
3213 if(CHILD(1).isMultiplication()) {
3214 for(size_t i2 = 0; i2 < CHILD(1).size(); i2++) {
3215 if(!CHILD(1)[i2].isUnit_exp()) {
3216 b_units = false;
3217 break;
3218 }
3219 }
3220 } else if(!CHILD(1).isUnit_exp()) {
3221 b_units = false;
3222 }
3223 }
3224 }
3225 if(colorize && tagtype == TAG_TYPE_TERMINAL) {
3226 if(b_units) print_str += (colorize == 2 ? "\033[0;92m" : "\033[0;32m");
3227 else if(b_num2) print_str += (colorize == 2 ? "\033[0;96m" : "\033[0;36m");
3228 }
3229 if(b_num && (po.number_fraction_format == FRACTION_DECIMAL || po.number_fraction_format == FRACTION_DECIMAL_EXACT)) {
3230 PrintOptions po2 = po;
3231 po2.number_fraction_format = FRACTION_FRACTIONAL;
3232 ips_n.wrap = CHILD(0).needsParenthesis(po2, ips_n, *this, 1, true, true);
3233 print_str += CHILD(0).print(po2, !b_units && !b_num2 && format, (b_units || b_num2) ? 0 : colorize, tagtype, ips_n);
3234 } else {
3235 ips_n.wrap = !b_units && CHILD(0).needsParenthesis(po, ips_n, *this, 1, true, true);
3236 print_str += CHILD(0).print(po, !b_units && !b_num2 && format, (b_units || b_num2) ? 0 : colorize, tagtype, ips_n);
3237 }
3238 if(po.use_unicode_signs && po.division_sign == DIVISION_SIGN_DIVISION && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_DIVISION, po.can_display_unicode_string_arg))) {
3239 if(po.spacious && !b_units && !b_num2) print_str += " ";
3240 print_str += SIGN_DIVISION;
3241 if(po.spacious && !b_units && !b_num2) print_str += " ";
3242 } else if(po.use_unicode_signs && po.division_sign == DIVISION_SIGN_DIVISION_SLASH && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_DIVISION_SLASH, po.can_display_unicode_string_arg))) {
3243 print_str += " " SIGN_DIVISION_SLASH " ";
3244 } else {
3245 if(po.spacious && !b_units && !b_num2) print_str += " ";
3246 print_str += "/";
3247 if(po.spacious && !b_units && !b_num2) print_str += " ";
3248 }
3249 if(b_num && (po.number_fraction_format == FRACTION_DECIMAL || po.number_fraction_format == FRACTION_DECIMAL_EXACT)) {
3250 PrintOptions po2 = po;
3251 po2.number_fraction_format = FRACTION_FRACTIONAL;
3252 ips_n.wrap = CHILD(1).needsParenthesis(po2, ips_n, *this, 2, true, true);
3253 print_str += CHILD(1).print(po2, !b_units && !b_num2 && format, (b_units || b_num2) ? 0 : colorize, tagtype, ips_n);
3254 } else {
3255 ips_n.wrap = CHILD(1).needsParenthesis(po, ips_n, *this, 2, true, true);
3256 print_str += CHILD(1).print(po, !b_units && !b_num2 && format, (b_units || b_num2) ? 0 : colorize, tagtype, ips_n);
3257 }
3258 if((b_units || b_num2) && colorize && tagtype == TAG_TYPE_TERMINAL) print_str += "\033[0m";
3259 break;
3260 }
3261 case STRUCT_POWER: {
3262 if(!po.negative_exponents && tagtype == TAG_TYPE_TERMINAL && po.use_unicode_signs && po.place_units_separately && !po.preserve_format && CHILD(0).isUnit() && CHILD(1).isInteger() && CHILD(1).number() >= 2 && CHILD(1).number() <= 9) {
3263 string s_super;
3264 if(CHILD(1).number() == 2) s_super = SIGN_POWER_2;
3265 else if(CHILD(1).number() == 3) s_super = SIGN_POWER_3;
3266 else if(CHILD(1).number() == 4) s_super = SIGN_POWER_4;
3267 else if(CHILD(1).number() == 5) s_super = SIGN_POWER_5;
3268 else if(CHILD(1).number() == 6) s_super = SIGN_POWER_6;
3269 else if(CHILD(1).number() == 7) s_super = SIGN_POWER_7;
3270 else if(CHILD(1).number() == 8) s_super = SIGN_POWER_8;
3271 else if(CHILD(1).number() == 9) s_super = SIGN_POWER_9;
3272 if(!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (s_super.c_str(), po.can_display_unicode_string_arg)) {
3273 if(colorize && tagtype == TAG_TYPE_TERMINAL) print_str = (colorize == 2 ? "\033[0;92m" : "\033[0;32m");
3274 ips_n.wrap = false;
3275 if(CHILD(0).isUnit() && po.use_unicode_signs && po.abbreviate_names && CHILD(0).unit() == CALCULATOR->getDegUnit()) {
3276 PrintOptions po2 = po;
3277 po2.use_unicode_signs = false;
3278 print_str += CHILD(0).print(po2, false, false, tagtype, ips_n);
3279 } else {
3280 print_str += CHILD(0).print(po, false, false, tagtype, ips_n);
3281 }
3282 print_str += s_super;
3283 if(colorize && tagtype == TAG_TYPE_TERMINAL) print_str += "\033[0m";
3284 break;
3285 }
3286 }
3287 ips_n.depth++;
3288 ips_n.power_depth++;
3289 ips_n.wrap = CHILD(0).needsParenthesis(po, ips_n, *this, 1, true, true);
3290 bool b_units = po.place_units_separately && !po.preserve_format && colorize && tagtype == TAG_TYPE_TERMINAL && CHILD(0).isUnit();
3291 if(b_units) print_str = colorize == 2 ? "\033[0;92m" : "\033[0;32m";
3292 PrintOptions po2 = po;
3293 if(CHILD(0).isUnit() && po.use_unicode_signs && po.abbreviate_names && CHILD(0).unit() == CALCULATOR->getDegUnit()) po2.use_unicode_signs = false;
3294 print_str += CHILD(0).print(po2, format, b_units ? 0 : colorize, tagtype, ips_n);
3295 print_str += "^";
3296 ips_n.wrap = CHILD(1).needsParenthesis(po, ips_n, *this, 2, true, true);
3297 po2.use_unicode_signs = po.use_unicode_signs;
3298 po2.show_ending_zeroes = false;
3299 print_str += CHILD(1).print(po2, format, b_units ? 0 : colorize, tagtype, ips_n);
3300 if(b_units) print_str += "\033[0m";
3301 break;
3302 }
3303 case STRUCT_COMPARISON: {
3304 ips_n.depth++;
3305 ips_n.wrap = CHILD(0).needsParenthesis(po, ips_n, *this, 1, true, true);
3306 print_str = CHILD(0).print(po, format, colorize, tagtype, ips_n);
3307 if(po.spacious) print_str += " ";
3308 switch(ct_comp) {
3309 case COMPARISON_EQUALS: {
3310 if(po.use_unicode_signs && po.interval_display != INTERVAL_DISPLAY_INTERVAL && isApproximate() && containsInterval() && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_ALMOST_EQUAL, po.can_display_unicode_string_arg))) print_str += SIGN_ALMOST_EQUAL;
3311 else print_str += "=";
3312 break;
3313 }
3314 case COMPARISON_NOT_EQUALS: {
3315 if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_NOT_EQUAL, po.can_display_unicode_string_arg))) print_str += SIGN_NOT_EQUAL;
3316 else print_str += "!=";
3317 break;
3318 }
3319 case COMPARISON_GREATER: {print_str += ">"; break;}
3320 case COMPARISON_LESS: {print_str += "<"; break;}
3321 case COMPARISON_EQUALS_GREATER: {
3322 if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_GREATER_OR_EQUAL, po.can_display_unicode_string_arg))) print_str += SIGN_GREATER_OR_EQUAL;
3323 else print_str += ">=";
3324 break;
3325 }
3326 case COMPARISON_EQUALS_LESS: {
3327 if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_LESS_OR_EQUAL, po.can_display_unicode_string_arg))) print_str += SIGN_LESS_OR_EQUAL;
3328 else print_str += "<=";
3329 break;
3330 }
3331 }
3332 if(po.spacious) print_str += " ";
3333 ips_n.wrap = CHILD(1).needsParenthesis(po, ips_n, *this, 2, true, true);
3334 print_str += CHILD(1).print(po, format, colorize, tagtype, ips_n);
3335 break;
3336 }
3337 case STRUCT_BITWISE_AND: {
3338 ips_n.depth++;
3339 for(size_t i = 0; i < SIZE; i++) {
3340 if(CALCULATOR->aborted()) return CALCULATOR->abortedMessage();
3341 if(i > 0) {
3342 if(po.spacious) print_str += " ";
3343 print_str += "&";
3344 if(po.spacious) print_str += " ";
3345 }
3346 ips_n.wrap = CHILD(i).needsParenthesis(po, ips_n, *this, i + 1, true, true);
3347 print_str += CHILD(i).print(po, format, colorize, tagtype, ips_n);
3348 }
3349 break;
3350 }
3351 case STRUCT_BITWISE_OR: {
3352 ips_n.depth++;
3353 for(size_t i = 0; i < SIZE; i++) {
3354 if(CALCULATOR->aborted()) return CALCULATOR->abortedMessage();
3355 if(i > 0) {
3356 if(po.spacious) print_str += " ";
3357 print_str += "|";
3358 if(po.spacious) print_str += " ";
3359 }
3360 ips_n.wrap = CHILD(i).needsParenthesis(po, ips_n, *this, i + 1, true, true);
3361 print_str += CHILD(i).print(po, format, colorize, tagtype, ips_n);
3362 }
3363 break;
3364 }
3365 case STRUCT_BITWISE_XOR: {
3366 ips_n.depth++;
3367 for(size_t i = 0; i < SIZE; i++) {
3368 if(CALCULATOR->aborted()) return CALCULATOR->abortedMessage();
3369 if(i > 0) {
3370 print_str += " ";
3371 print_str += "xor";
3372 print_str += " ";
3373 }
3374 ips_n.wrap = CHILD(i).needsParenthesis(po, ips_n, *this, i + 1, true, true);
3375 print_str += CHILD(i).print(po, format, colorize, tagtype, ips_n);
3376 }
3377 break;
3378 }
3379 case STRUCT_BITWISE_NOT: {
3380 print_str = "~";
3381 ips_n.depth++;
3382 ips_n.wrap = CHILD(0).needsParenthesis(po, ips_n, *this, 1, true, true);
3383 print_str += CHILD(0).print(po, format, colorize, tagtype, ips_n);
3384 break;
3385 }
3386 case STRUCT_LOGICAL_AND: {
3387 ips_n.depth++;
3388 if(!po.preserve_format && SIZE == 2 && CHILD(0).isComparison() && CHILD(1).isComparison() && CHILD(0).comparisonType() != COMPARISON_EQUALS && CHILD(0).comparisonType() != COMPARISON_NOT_EQUALS && CHILD(1).comparisonType() != COMPARISON_EQUALS && CHILD(1).comparisonType() != COMPARISON_NOT_EQUALS && CHILD(0)[0] == CHILD(1)[0]) {
3389 ips_n.wrap = CHILD(0)[1].needsParenthesis(po, ips_n, CHILD(0), 2, true, true);
3390 print_str += CHILD(0)[1].print(po, format, colorize, tagtype, ips_n);
3391 if(po.spacious) print_str += " ";
3392 switch(CHILD(0).comparisonType()) {
3393 case COMPARISON_LESS: {print_str += ">"; break;}
3394 case COMPARISON_GREATER: {print_str += "<"; break;}
3395 case COMPARISON_EQUALS_LESS: {
3396 if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_GREATER_OR_EQUAL, po.can_display_unicode_string_arg))) print_str += SIGN_GREATER_OR_EQUAL;
3397 else print_str += ">=";
3398 break;
3399 }
3400 case COMPARISON_EQUALS_GREATER: {
3401 if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_LESS_OR_EQUAL, po.can_display_unicode_string_arg))) print_str += SIGN_LESS_OR_EQUAL;
3402 else print_str += "<=";
3403 break;
3404 }
3405 default: {}
3406 }
3407 if(po.spacious) print_str += " ";
3408
3409 ips_n.wrap = CHILD(0)[0].needsParenthesis(po, ips_n, CHILD(0), 1, true, true);
3410 print_str += CHILD(0)[0].print(po, format, colorize, tagtype, ips_n);
3411
3412 if(po.spacious) print_str += " ";
3413 switch(CHILD(1).comparisonType()) {
3414 case COMPARISON_GREATER: {print_str += ">"; break;}
3415 case COMPARISON_LESS: {print_str += "<"; break;}
3416 case COMPARISON_EQUALS_GREATER: {
3417 if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_GREATER_OR_EQUAL, po.can_display_unicode_string_arg))) print_str += SIGN_GREATER_OR_EQUAL;
3418 else print_str += ">=";
3419 break;
3420 }
3421 case COMPARISON_EQUALS_LESS: {
3422 if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_LESS_OR_EQUAL, po.can_display_unicode_string_arg))) print_str += SIGN_LESS_OR_EQUAL;
3423 else print_str += "<=";
3424 break;
3425 }
3426 default: {}
3427 }
3428 if(po.spacious) print_str += " ";
3429
3430 ips_n.wrap = CHILD(1)[1].needsParenthesis(po, ips_n, CHILD(1), 2, true, true);
3431 print_str += CHILD(1)[1].print(po, format, colorize, tagtype, ips_n);
3432
3433 break;
3434 }
3435 for(size_t i = 0; i < SIZE; i++) {
3436 if(CALCULATOR->aborted()) return CALCULATOR->abortedMessage();
3437 if(i > 0) {
3438 if(po.spell_out_logical_operators) {
3439 print_str += " ";
3440 print_str += _("and");
3441 print_str += " ";
3442 } else {
3443 if(po.spacious) print_str += " ";
3444 print_str += "&&";
3445 if(po.spacious) print_str += " ";
3446 }
3447 }
3448 ips_n.wrap = CHILD(i).needsParenthesis(po, ips_n, *this, i + 1, true, true);
3449 print_str += CHILD(i).print(po, format, colorize, tagtype, ips_n);
3450 }
3451 break;
3452 }
3453 case STRUCT_LOGICAL_OR: {
3454 ips_n.depth++;
3455 for(size_t i = 0; i < SIZE; i++) {
3456 if(CALCULATOR->aborted()) return CALCULATOR->abortedMessage();
3457 if(i > 0) {
3458 if(po.spell_out_logical_operators) {
3459 print_str += " ";
3460 print_str += _("or");
3461 print_str += " ";
3462 } else {
3463 if(po.spacious) print_str += " ";
3464 print_str += "||";
3465 if(po.spacious) print_str += " ";
3466 }
3467 }
3468 ips_n.wrap = CHILD(i).needsParenthesis(po, ips_n, *this, i + 1, true, true);
3469 print_str += CHILD(i).print(po, format, colorize, tagtype, ips_n);
3470 }
3471 break;
3472 }
3473 case STRUCT_LOGICAL_XOR: {
3474 ips_n.depth++;
3475 for(size_t i = 0; i < SIZE; i++) {
3476 if(CALCULATOR->aborted()) return CALCULATOR->abortedMessage();
3477 if(i > 0) {
3478 print_str += " ";
3479 print_str += "xor";
3480 print_str += " ";
3481 }
3482 ips_n.wrap = CHILD(i).needsParenthesis(po, ips_n, *this, i + 1, true, true);
3483 print_str += CHILD(i).print(po, format, colorize, tagtype, ips_n);
3484 }
3485 break;
3486 }
3487 case STRUCT_LOGICAL_NOT: {
3488 print_str = "!";
3489 ips_n.depth++;
3490 ips_n.wrap = CHILD(0).needsParenthesis(po, ips_n, *this, 1, true, true);
3491 print_str += CHILD(0).print(po, format, colorize, tagtype, ips_n);
3492 break;
3493 }
3494 case STRUCT_VECTOR: {
3495 ips_n.depth++;
3496 print_str = "[";
3497 for(size_t i = 0; i < SIZE; i++) {
3498 if(CALCULATOR->aborted()) return CALCULATOR->abortedMessage();
3499 if(i > 0) {
3500 print_str += po.comma();
3501 if(po.spacious) print_str += " ";
3502 }
3503 ips_n.wrap = CHILD(i).needsParenthesis(po, ips_n, *this, i + 1, true, true);
3504 print_str += CHILD(i).print(po, format, colorize, tagtype, ips_n);
3505 }
3506 print_str += "]";
3507 break;
3508 }
3509 case STRUCT_UNIT: {
3510 const ExpressionName *ename = &o_unit->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, b_plural, po.use_reference_names || (po.preserve_format && o_unit->isCurrency()), po.can_display_unicode_string_function, po.can_display_unicode_string_arg);
3511 if(o_prefix) print_str += o_prefix->name(po.abbreviate_names && ename->abbreviation, po.use_unicode_signs, po.can_display_unicode_string_function, po.can_display_unicode_string_arg);
3512 print_str += ename->name;
3513 if(ename->suffix && !po.preserve_format && !po.use_reference_names) {
3514 size_t i = print_str.rfind('_');
3515 if(i != string::npos && i + 5 <= print_str.length() && print_str.substr(print_str.length() - 4, 4) == "unit") {
3516 if(i + 5 == print_str.length()) {
3517 print_str = print_str.substr(0, i);
3518 if(po.hide_underscore_spaces) gsub("_", " ", print_str);
3519 } else {
3520 print_str = print_str.substr(0, print_str.length() - 4);
3521 }
3522 }
3523 }
3524 if(po.hide_underscore_spaces && !ename->suffix) {
3525 gsub("_", " ", print_str);
3526 }
3527 if(colorize && tagtype == TAG_TYPE_TERMINAL) {
3528 print_str.insert(0, colorize == 2 ? "\033[0;92m" : "\033[0;32m");
3529 print_str += "\033[0m";
3530 }
3531 break;
3532 }
3533 case STRUCT_VARIABLE: {
3534 const ExpressionName *ename = &o_variable->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg);
3535 print_str += ename->name;
3536 if(ename->suffix && !po.preserve_format && !po.use_reference_names) {
3537 size_t i = print_str.rfind('_');
3538 if(i != string::npos && i + 9 <= print_str.length() && print_str.substr(print_str.length() - 8, 8) == "constant") {
3539 if(i + 9 == print_str.length()) {
3540 print_str = print_str.substr(0, i);
3541 if(po.hide_underscore_spaces) gsub("_", " ", print_str);
3542 } else {
3543 print_str = print_str.substr(0, print_str.length() - 8);
3544 }
3545 }
3546 }
3547 if(po.hide_underscore_spaces && !ename->suffix) {
3548 gsub("_", " ", print_str);
3549 }
3550 if(colorize && tagtype == TAG_TYPE_TERMINAL) {
3551 if(o_variable->isKnown()) {
3552 print_str.insert(0, colorize == 2 ? "\033[0;93m" : "\033[0;33m");
3553 } else {
3554 if(format) print_str.insert(0, "\033[3m");
3555 print_str.insert(0, colorize == 2 ? "\033[0;93m" : "\033[0;33m");
3556 if(format) print_str += "\033[23m";
3557 }
3558 print_str += "\033[0m";
3559 }
3560 break;
3561 }
3562 case STRUCT_FUNCTION: {
3563 ips_n.depth++;
3564 if(o_function->id() == FUNCTION_ID_UNCERTAINTY && SIZE == 3 && CHILD(2).isZero()) {
3565 MathStructure *mmid = NULL, *munc = NULL;
3566 if(o_function->id() == FUNCTION_ID_UNCERTAINTY) {
3567 mmid = &CHILD(0);
3568 munc = &CHILD(1);
3569 } else if(CHILD(0)[0].equals(CHILD(1)[0], true, true)) {
3570 mmid = &CHILD(0)[0];
3571 if(CHILD(0)[1].isNegate() && CHILD(0)[1][0].equals(CHILD(1)[1], true, true)) munc = &CHILD(1)[1];
3572 if(CHILD(1)[1].isNegate() && CHILD(1)[1][0].equals(CHILD(0)[1], true, true)) munc = &CHILD(0)[1];
3573 } else if(CHILD(0)[1].equals(CHILD(1)[1], true, true)) {
3574 mmid = &CHILD(0)[1];
3575 if(CHILD(0)[0].isNegate() && CHILD(0)[0][0].equals(CHILD(1)[0], true, true)) munc = &CHILD(1)[0];
3576 if(CHILD(1)[0].isNegate() && CHILD(1)[0][0].equals(CHILD(0)[0], true, true)) munc = &CHILD(0)[0];
3577 } else if(CHILD(0)[0].equals(CHILD(1)[1], true, true)) {
3578 mmid = &CHILD(0)[0];
3579 if(CHILD(0)[1].isNegate() && CHILD(0)[1][0].equals(CHILD(1)[0], true, true)) munc = &CHILD(1)[0];
3580 if(CHILD(1)[0].isNegate() && CHILD(1)[0][0].equals(CHILD(0)[1], true, true)) munc = &CHILD(0)[1];
3581 } else if(CHILD(0)[1].equals(CHILD(1)[0], true, true)) {
3582 mmid = &CHILD(0)[0];
3583 if(CHILD(0)[0].isNegate() && CHILD(0)[0][0].equals(CHILD(1)[1], true, true)) munc = &CHILD(1)[1];
3584 if(CHILD(1)[1].isNegate() && CHILD(1)[1][0].equals(CHILD(0)[0], true, true)) munc = &CHILD(0)[0];
3585 }
3586 if(mmid && munc) {
3587 PrintOptions po2 = po;
3588 po2.show_ending_zeroes = false;
3589 po2.number_fraction_format = FRACTION_DECIMAL;
3590 ips_n.wrap = !CHILD(0).isNumber();
3591 print_str += CHILD(0).print(po2, format, colorize, tagtype, ips_n);
3592 print_str += SIGN_PLUSMINUS;
3593 ips_n.wrap = !CHILD(1).isNumber();
3594 print_str += CHILD(1).print(po2, format, colorize, tagtype, ips_n);
3595 break;
3596 }
3597 }
3598 const ExpressionName *ename = &o_function->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg);
3599 print_str += ename->name;
3600 if(po.hide_underscore_spaces && !ename->suffix) {
3601 gsub("_", " ", print_str);
3602 }
3603 print_str += "(";
3604 size_t argcount = SIZE;
3605 if(o_function->id() == FUNCTION_ID_SIGNUM && argcount > 1) {
3606 argcount = 1;
3607 } else if(o_function->maxargs() > 0 && o_function->minargs() < o_function->maxargs() && SIZE > (size_t) o_function->minargs()) {
3608 while(true) {
3609 string defstr = o_function->getDefaultValue(argcount);
3610 Argument *arg = o_function->getArgumentDefinition(argcount);
3611 remove_blank_ends(defstr);
3612 if(defstr.empty()) break;
3613 if(CHILD(argcount - 1).isUndefined() && defstr == "undefined") {
3614 argcount--;
3615 } else if(arg && arg->type() == ARGUMENT_TYPE_SYMBOLIC && ((argcount > 1 && defstr == "undefined" && CHILD(argcount - 1) == CHILD(0).find_x_var()) || (defstr == "\"\"" && CHILD(argcount - 1) == ""))) {
3616 argcount--;
3617 } else if(CHILD(argcount - 1).isVariable() && (!arg || arg->type() != ARGUMENT_TYPE_TEXT) && defstr == CHILD(argcount - 1).variable()->referenceName()) {
3618 argcount--;
3619 } else if(CHILD(argcount - 1).isInteger() && (!arg || arg->type() != ARGUMENT_TYPE_TEXT) && defstr.find_first_not_of(NUMBERS) == string::npos && CHILD(argcount - 1).number() == s2i(defstr)) {
3620 argcount--;
3621 } else if(CHILD(argcount - 1).isSymbolic() && arg && arg->type() == ARGUMENT_TYPE_TEXT && (CHILD(argcount - 1).symbol() == defstr || (defstr == "\"\"" && CHILD(argcount - 1).symbol().empty()))) {
3622 argcount--;
3623 } else {
3624 break;
3625 }
3626 if(argcount == 0 || argcount == (size_t) o_function->minargs()) break;
3627 }
3628 }
3629 for(size_t i = 0; i < argcount; i++) {
3630 if(CALCULATOR->aborted()) return CALCULATOR->abortedMessage();
3631 if(i > 0) {
3632 print_str += po.comma();
3633 if(po.spacious) print_str += " ";
3634 }
3635 ips_n.wrap = CHILD(i).needsParenthesis(po, ips_n, *this, i + 1, true, true);
3636 if(o_function->id() == FUNCTION_ID_INTERVAL) {
3637 PrintOptions po2 = po;
3638 po2.show_ending_zeroes = false;
3639 print_str += CHILD(i).print(po2, format, colorize, tagtype, ips_n);
3640 } else {
3641 print_str += CHILD(i).print(po, format, colorize, tagtype, ips_n);
3642 }
3643 }
3644 print_str += ")";
3645 break;
3646 }
3647 case STRUCT_UNDEFINED: {
3648 if(colorize && tagtype == TAG_TYPE_TERMINAL) print_str = (colorize == 2 ? "\033[0;91m" : "\033[0;31m");
3649 print_str += _("undefined");
3650 if(colorize && tagtype == TAG_TYPE_TERMINAL) print_str += "\033[0m";
3651 break;
3652 }
3653 }
3654 if(CALCULATOR->aborted()) {
3655 if(colorize && tagtype == TAG_TYPE_TERMINAL) {
3656 print_str = (colorize == 2 ? "\033[0;91m" : "\033[0;31m");
3657 print_str += CALCULATOR->abortedMessage();
3658 print_str += "\033[0m";
3659 } else {
3660 print_str = CALCULATOR->abortedMessage();
3661 }
3662 }
3663 if(ips.wrap) {
3664 print_str.insert(0, "(");
3665 print_str += ")";
3666 }
3667 return print_str;
3668 }
3669
3670