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