1 /*
2     Qalculate
3 
4     Copyright (C) 2003-2007, 2008, 2016-2021  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 "Calculator.h"
15 #include "BuiltinFunctions.h"
16 #include "util.h"
17 #include "MathStructure.h"
18 #include "Unit.h"
19 #include "Variable.h"
20 #include "Function.h"
21 #include "DataSet.h"
22 #include "ExpressionItem.h"
23 #include "Prefix.h"
24 #include "Number.h"
25 #include "QalculateDateTime.h"
26 
27 #include <locale.h>
28 #include <unistd.h>
29 #include <time.h>
30 #include <utime.h>
31 #include <limits.h>
32 #include <sys/types.h>
33 
34 #ifdef HAVE_ICU
35 #	include <unicode/ucasemap.h>
36 #endif
37 
38 #include "MathStructure-support.h"
39 
40 using std::string;
41 using std::cout;
42 using std::vector;
43 using std::endl;
44 using std::iterator;
45 
46 #include "Calculator_p.h"
47 
PrintOptions()48 PrintOptions::PrintOptions() : min_exp(EXP_PRECISION), base(BASE_DECIMAL), base_display(BASE_DISPLAY_NONE), lower_case_numbers(false), lower_case_e(false), number_fraction_format(FRACTION_DECIMAL), indicate_infinite_series(false), show_ending_zeroes(true), abbreviate_names(true), use_reference_names(false), place_units_separately(true), use_unit_prefixes(true), use_prefixes_for_all_units(false), use_prefixes_for_currencies(false), use_all_prefixes(false), use_denominator_prefix(true), negative_exponents(false), short_multiplication(true), limit_implicit_multiplication(false), allow_non_usable(false), use_unicode_signs(false), multiplication_sign(MULTIPLICATION_SIGN_DOT), division_sign(DIVISION_SIGN_DIVISION_SLASH), spacious(true), excessive_parenthesis(false), halfexp_to_sqrt(true), min_decimals(0), max_decimals(-1), use_min_decimals(true), use_max_decimals(true), round_halfway_to_even(false), improve_division_multipliers(true), prefix(NULL), is_approximate(NULL), can_display_unicode_string_function(NULL), can_display_unicode_string_arg(NULL), hide_underscore_spaces(false), preserve_format(false), allow_factorization(false), spell_out_logical_operators(false), restrict_to_parent_precision(true), restrict_fraction_length(false), exp_to_root(false), preserve_precision(false), interval_display(INTERVAL_DISPLAY_INTERVAL), digit_grouping(DIGIT_GROUPING_NONE), date_time_format(DATE_TIME_FORMAT_ISO), time_zone(TIME_ZONE_LOCAL), custom_time_zone(0), twos_complement(true), hexadecimal_twos_complement(false), binary_bits(0) {}
49 
comma() const50 const string &PrintOptions::comma() const {if(comma_sign.empty()) return CALCULATOR->getComma(); return comma_sign;}
decimalpoint() const51 const string &PrintOptions::decimalpoint() const {if(decimalpoint_sign.empty()) return CALCULATOR->getDecimalPoint(); return decimalpoint_sign;}
52 
InternalPrintStruct()53 InternalPrintStruct::InternalPrintStruct() : depth(0), power_depth(0), division_depth(0), wrap(false), num(NULL), den(NULL), re(NULL), im(NULL), exp(NULL), minus(NULL), exp_minus(NULL), parent_approximate(false), parent_precision(-1), iexp(NULL) {}
54 
ParseOptions()55 ParseOptions::ParseOptions() : variables_enabled(true), functions_enabled(true), unknowns_enabled(true), units_enabled(true), rpn(false), base(BASE_DECIMAL), limit_implicit_multiplication(false), read_precision(DONT_READ_PRECISION), dot_as_separator(false), brackets_as_parentheses(false), angle_unit(ANGLE_UNIT_NONE), unended_function(NULL), preserve_format(false), default_dataset(NULL), parsing_mode(PARSING_MODE_ADAPTIVE), twos_complement(false), hexadecimal_twos_complement(false) {}
56 
EvaluationOptions()57 EvaluationOptions::EvaluationOptions() : approximation(APPROXIMATION_TRY_EXACT), sync_units(true), sync_nonlinear_unit_relations(true), keep_prefixes(false), calculate_variables(true), calculate_functions(true), test_comparisons(true), isolate_x(true), expand(true), combine_divisions(false), reduce_divisions(true), allow_complex(true), allow_infinite(true), assume_denominators_nonzero(true), warn_about_denominators_assumed_nonzero(false), split_squares(true), keep_zero_units(true), auto_post_conversion(POST_CONVERSION_OPTIMAL), mixed_units_conversion(MIXED_UNITS_CONVERSION_DEFAULT), structuring(STRUCTURING_SIMPLIFY), isolate_var(NULL), do_polynomial_division(true), protected_function(NULL), complex_number_form(COMPLEX_NUMBER_FORM_RECTANGULAR), local_currency_conversion(true), transform_trigonometric_functions(true), interval_calculation(INTERVAL_CALCULATION_VARIANCE_FORMULA) {}
58 
59 /*#include <time.h>
60 #include <sys/time.h>
61 
62 struct timeval tvtime;
63 long int usecs, secs, usecs2, usecs3;
64 
65 #define PRINT_TIME(x) gettimeofday(&tvtime, NULL); usecs2 = tvtime.tv_usec - usecs + (tvtime.tv_sec - secs) * 1000000; printf("%s %li\n", x, usecs2);
66 #define PRINT_TIMEDIFF(x) gettimeofday(&tvtime, NULL); printf("%s %li\n", x, tvtime.tv_usec - usecs + (tvtime.tv_sec - secs) * 1000000 - usecs2); usecs2 = tvtime.tv_usec - usecs + (tvtime.tv_sec - secs) * 1000000;
67 #define ADD_TIME1 gettimeofday(&tvtime, NULL); usecs2 = tvtime.tv_usec - usecs + (tvtime.tv_sec - secs) * 1000000;
68 #define ADD_TIME2 gettimeofday(&tvtime, NULL); usecs3 += tvtime.tv_usec - usecs + (tvtime.tv_sec - secs) * 1000000 - usecs2; */
69 
70 typedef void (*CREATEPLUG_PROC)();
71 
CalculatorMessage(string message_,MessageType type_,int cat_,int stage_)72 CalculatorMessage::CalculatorMessage(string message_, MessageType type_, int cat_, int stage_) {
73 	mtype = type_;
74 	i_stage = stage_;
75 	i_cat = cat_;
76 	smessage = message_;
77 }
CalculatorMessage(const CalculatorMessage & e)78 CalculatorMessage::CalculatorMessage(const CalculatorMessage &e) {
79 	mtype = e.type();
80 	i_stage = e.stage();
81 	i_cat = e.category();
82 	smessage = e.message();
83 }
message() const84 string CalculatorMessage::message() const {
85 	return smessage;
86 }
c_message() const87 const char* CalculatorMessage::c_message() const {
88 	return smessage.c_str();
89 }
type() const90 MessageType CalculatorMessage::type() const {
91 	return mtype;
92 }
stage() const93 int CalculatorMessage::stage() const {
94 	return i_stage;
95 }
category() const96 int CalculatorMessage::category() const {
97 	return i_cat;
98 }
99 
addStringAlternative(string replacement,string standard)100 void Calculator::addStringAlternative(string replacement, string standard) {
101 	signs.push_back(replacement);
102 	real_signs.push_back(standard);
103 }
delStringAlternative(string replacement,string standard)104 bool Calculator::delStringAlternative(string replacement, string standard) {
105 	for(size_t i = 0; i < signs.size(); i++) {
106 		if(signs[i] == replacement && real_signs[i] == standard) {
107 			signs.erase(signs.begin() + i);
108 			real_signs.erase(real_signs.begin() + i);
109 			return true;
110 		}
111 	}
112 	return false;
113 }
addDefaultStringAlternative(string replacement,string standard)114 void Calculator::addDefaultStringAlternative(string replacement, string standard) {
115 	default_signs.push_back(replacement);
116 	default_real_signs.push_back(standard);
117 }
delDefaultStringAlternative(string replacement,string standard)118 bool Calculator::delDefaultStringAlternative(string replacement, string standard) {
119 	for(size_t i = 0; i < default_signs.size(); i++) {
120 		if(default_signs[i] == replacement && default_real_signs[i] == standard) {
121 			default_signs.erase(default_signs.begin() + i);
122 			default_real_signs.erase(default_real_signs.begin() + i);
123 			return true;
124 		}
125 	}
126 	return false;
127 }
128 
129 Calculator *calculator = NULL;
130 
131 MathStructure m_undefined, m_empty_vector, m_empty_matrix, m_zero, m_one, m_minus_one, m_one_i;
132 Number nr_zero, nr_one, nr_two, nr_three, nr_minus_one, nr_one_i, nr_minus_i, nr_half, nr_minus_half, nr_plus_inf, nr_minus_inf;
133 EvaluationOptions no_evaluation;
134 ExpressionName empty_expression_name;
135 extern gmp_randstate_t randstate;
136 #ifdef HAVE_ICU
137 	extern UCaseMap *ucm;
138 #endif
139 
140 #define BITWISE_XOR "⊻"
141 
Calculator()142 Calculator::Calculator() {
143 	b_ignore_locale = false;
144 
145 #ifdef ENABLE_NLS
146 	if(!b_ignore_locale) {
147 		bindtextdomain(GETTEXT_PACKAGE, getPackageLocaleDir().c_str());
148 		bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
149 	}
150 #endif
151 
152 	if(b_ignore_locale) {
153 		char *current_lc_monetary = setlocale(LC_MONETARY, "");
154 		if(current_lc_monetary) saved_locale = strdup(current_lc_monetary);
155 		else saved_locale = NULL;
156 		setlocale(LC_ALL, "C");
157 		if(saved_locale) {
158 			setlocale(LC_MONETARY, saved_locale);
159 			free(saved_locale);
160 			saved_locale = NULL;
161 		}
162 	} else {
163 		setlocale(LC_ALL, "");
164 	}
165 
166 
167 	gmp_randinit_default(randstate);
168 	gmp_randseed_ui(randstate, (unsigned long int) time(NULL));
169 
170 	priv = new Calculator_p;
171 	priv->custom_input_base_i = 0;
172 	priv->ids_i = 0;
173 	priv->local_currency = NULL;
174 	priv->use_binary_prefixes = 0;
175 	priv->temperature_calculation = TEMPERATURE_CALCULATION_HYBRID;
176 
177 #ifdef HAVE_ICU
178 	UErrorCode err = U_ZERO_ERROR;
179 	ucm = ucasemap_open(NULL, 0, &err);
180 #endif
181 
182 	srand(time(NULL));
183 
184 	exchange_rates_time[0] = 0;
185 	exchange_rates_time[1] = (time_t) 447984L * (time_t) 3600;
186 	exchange_rates_time[2] = 0;
187 	priv->exchange_rates_time2[0] = (time_t) 447984L * (time_t) 3600;
188 	exchange_rates_check_time[0] = 0;
189 	exchange_rates_check_time[1] = (time_t) 447984L * (time_t) 3600;
190 	exchange_rates_check_time[2] = 0;
191 	priv->exchange_rates_check_time2[0] = (time_t) 447984L * (time_t) 3600;
192 	b_exchange_rates_warning_enabled = true;
193 	b_exchange_rates_used = 0;
194 
195 	i_aborted = 0;
196 	b_controlled = false;
197 	i_timeout = 0;
198 
199 	setPrecision(DEFAULT_PRECISION);
200 	b_interval = true;
201 	i_stop_interval = 0;
202 	i_start_interval = 0;
203 
204 	b_var_units = true;
205 
206 	addStringAlternative(SIGN_DIVISION, DIVISION);
207 	addStringAlternative(SIGN_DIVISION_SLASH, DIVISION);
208 	addStringAlternative("⁄", DIVISION);
209 	addStringAlternative(SIGN_MULTIPLICATION, MULTIPLICATION);
210 	addStringAlternative(SIGN_MULTIDOT, MULTIPLICATION);
211 	addStringAlternative(SIGN_MIDDLEDOT, MULTIPLICATION);
212 	addStringAlternative(SIGN_MULTIBULLET, MULTIPLICATION);
213 	addStringAlternative(SIGN_SMALLCIRCLE, MULTIPLICATION);
214 	addStringAlternative(SIGN_MINUS, MINUS);
215 	addStringAlternative("–", MINUS);
216 	addStringAlternative(SIGN_PLUS, PLUS);
217 	addStringAlternative(SIGN_NOT_EQUAL, " " NOT EQUALS);
218 	addStringAlternative(SIGN_GREATER_OR_EQUAL, GREATER EQUALS);
219 	addStringAlternative(SIGN_LESS_OR_EQUAL, LESS EQUALS);
220 	addStringAlternative(";", COMMA);
221 	addStringAlternative("\t", SPACE);
222 	addStringAlternative("\n", SPACE);
223 	addStringAlternative(" ", SPACE);
224 	addStringAlternative(" ", SPACE);
225 	addStringAlternative(" ", SPACE);
226 	addStringAlternative("**", POWER);
227 	addStringAlternative("↊", "X");
228 	addStringAlternative("↋", "E");
229 	addStringAlternative("∧", BITWISE_AND);
230 	addStringAlternative("∨", BITWISE_OR);
231 	addStringAlternative("¬", BITWISE_NOT);
232 	addStringAlternative(SIGN_MICRO, "μ");
233 
234 	per_str = _("per");
235 	per_str_len = per_str.length();
236 	times_str = _("times");
237 	times_str_len = times_str.length();
238 	plus_str = _("plus");
239 	plus_str_len = plus_str.length();
240 	minus_str = _("minus");
241 	minus_str_len = minus_str.length();
242 	and_str = _("and");
243 	if(and_str == "and") and_str = "";
244 	and_str_len = and_str.length();
245 	AND_str = "AND";
246 	AND_str_len = AND_str.length();
247 	or_str = _("or");
248 	if(or_str == "or") or_str = "";
249 	or_str_len = or_str.length();
250 	OR_str = "OR";
251 	OR_str_len = OR_str.length();
252 	XOR_str = "XOR";
253 	XOR_str_len = XOR_str.length();
254 
255 	char *current_lc_numeric = setlocale(LC_NUMERIC, NULL);
256 	if(current_lc_numeric) saved_locale = strdup(current_lc_numeric);
257 	else saved_locale = NULL;
258 	struct lconv *lc = localeconv();
259 	if(!lc) {
260 		setlocale(LC_NUMERIC, "C");
261 		lc = localeconv();
262 	}
263 	place_currency_sign_before = lc->p_cs_precedes;
264 	place_currency_sign_before_negative = lc->n_cs_precedes;
265 #ifdef HAVE_STRUCT_LCONV_INT_P_CS_PRECEDES
266  	place_currency_code_before = lc->int_p_cs_precedes;
267 #else
268 	place_currency_code_before = place_currency_sign_before;
269 #endif
270 #ifdef HAVE_STRUCT_LCONV_INT_N_CS_PRECEDES
271 	place_currency_code_before_negative = lc->int_n_cs_precedes;
272 #else
273 	place_currency_code_before_negative = place_currency_sign_before_negative;
274 #endif
275 	local_digit_group_separator = lc->thousands_sep;
276 	if((local_digit_group_separator.length() == 1 && local_digit_group_separator[0] < 0) || local_digit_group_separator == " ") local_digit_group_separator = " ";
277 	else if(local_digit_group_separator == " ") local_digit_group_separator = " ";
278 	local_digit_group_format = lc->grouping;
279 	remove_blank_ends(local_digit_group_format);
280 	default_dot_as_separator = (local_digit_group_separator == ".");
281 	if(strcmp(lc->decimal_point, ",") == 0) {
282 		DOT_STR = ",";
283 		DOT_S = ".,";
284 		COMMA_STR = ";";
285 		COMMA_S = ";";
286 	} else {
287 		DOT_STR = ".";
288 		DOT_S = ".";
289 		COMMA_STR = ",";
290 		COMMA_S = ",;";
291 	}
292 	setlocale(LC_NUMERIC, "C");
293 
294 	NAME_NUMBER_PRE_S = "_#";
295 	NAME_NUMBER_PRE_STR = "_";
296 
297 	//"to"-operator
298 	string str = _("to");
299 	local_to = (str != "to");
300 
301 	decimal_null_prefix = new DecimalPrefix(0, "", "");
302 	binary_null_prefix = new BinaryPrefix(0, "", "");
303 	m_undefined.setUndefined();
304 	m_empty_vector.clearVector();
305 	m_empty_matrix.clearMatrix();
306 	m_zero.clear();
307 	m_one.set(1, 1, 0);
308 	m_minus_one.set(-1, 1, 0);
309 	nr_zero.clear();
310 	nr_one.set(1, 1, 0);
311 	nr_two.set(2, 1, 0);
312 	nr_three.set(3, 1, 0);
313 	nr_half.set(1, 2, 0);
314 	nr_minus_half.set(-1, 2, 0);
315 	nr_one_i.setImaginaryPart(1, 1, 0);
316 	nr_minus_i.setImaginaryPart(-1, 1, 0);
317 	m_one_i.set(nr_one_i);
318 	nr_minus_one.set(-1, 1, 0);
319 	nr_plus_inf.setPlusInfinity();
320 	nr_minus_inf.setMinusInfinity();
321 	no_evaluation.approximation = APPROXIMATION_EXACT;
322 	no_evaluation.structuring = STRUCTURING_NONE;
323 	no_evaluation.sync_units = false;
324 
325 	save_printoptions.decimalpoint_sign = ".";
326 	save_printoptions.comma_sign = ",";
327 	save_printoptions.use_reference_names = true;
328 	save_printoptions.preserve_precision = true;
329 	save_printoptions.interval_display = INTERVAL_DISPLAY_INTERVAL;
330 	save_printoptions.limit_implicit_multiplication = true;
331 	save_printoptions.spacious = false;
332 	save_printoptions.number_fraction_format = FRACTION_FRACTIONAL;
333 	save_printoptions.short_multiplication = false;
334 	save_printoptions.show_ending_zeroes = false;
335 	save_printoptions.use_unit_prefixes = false;
336 
337 	message_printoptions.interval_display = INTERVAL_DISPLAY_PLUSMINUS;
338 	message_printoptions.spell_out_logical_operators = true;
339 	message_printoptions.number_fraction_format = FRACTION_FRACTIONAL;
340 
341 	default_user_evaluation_options.structuring = STRUCTURING_SIMPLIFY;
342 
343 	default_assumptions = new Assumptions;
344 	default_assumptions->setType(ASSUMPTION_TYPE_REAL);
345 	default_assumptions->setSign(ASSUMPTION_SIGN_UNKNOWN);
346 
347 	u_rad = NULL; u_gra = NULL; u_deg = NULL;
348 
349 	b_save_called = false;
350 
351 	ILLEGAL_IN_NAMES = "\a\b" + DOT_S + RESERVED OPERATORS SPACES PARENTHESISS VECTOR_WRAPS COMMAS;
352 	ILLEGAL_IN_NAMES_MINUS_SPACE_STR = "\a\b" + DOT_S + RESERVED OPERATORS PARENTHESISS VECTOR_WRAPS COMMAS;
353 	ILLEGAL_IN_UNITNAMES = ILLEGAL_IN_NAMES + NUMBERS;
354 	b_argument_errors = true;
355 	current_stage = MESSAGE_STAGE_UNSET;
356 	calculator = this;
357 	srand48(time(0));
358 
359 	addBuiltinVariables();
360 	addBuiltinFunctions();
361 	addBuiltinUnits();
362 
363 	disable_errors_ref = 0;
364 	b_busy = false;
365 	b_gnuplot_open = false;
366 	gnuplot_pipe = NULL;
367 
368 	calculate_thread = new CalculateThread;
369 }
Calculator(bool ignore_locale)370 Calculator::Calculator(bool ignore_locale) {
371 
372 	b_ignore_locale = ignore_locale;
373 
374 #ifdef ENABLE_NLS
375 	if(!b_ignore_locale) {
376 		bindtextdomain(GETTEXT_PACKAGE, getPackageLocaleDir().c_str());
377 		bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
378 	}
379 #endif
380 
381 	if(b_ignore_locale) {
382 		char *current_lc_monetary = setlocale(LC_MONETARY, "");
383 		if(current_lc_monetary) saved_locale = strdup(current_lc_monetary);
384 		else saved_locale = NULL;
385 		setlocale(LC_ALL, "C");
386 		if(saved_locale) {
387 			setlocale(LC_MONETARY, saved_locale);
388 			free(saved_locale);
389 			saved_locale = NULL;
390 		}
391 	} else {
392 		setlocale(LC_ALL, "");
393 	}
394 
395 
396 	gmp_randinit_default(randstate);
397 	gmp_randseed_ui(randstate, (unsigned long int) time(NULL));
398 
399 	priv = new Calculator_p;
400 	priv->custom_input_base_i = 0;
401 	priv->ids_i = 0;
402 	priv->local_currency = NULL;
403 	priv->use_binary_prefixes = 0;
404 	priv->temperature_calculation = TEMPERATURE_CALCULATION_HYBRID;
405 
406 #ifdef HAVE_ICU
407 	UErrorCode err = U_ZERO_ERROR;
408 	ucm = ucasemap_open(NULL, 0, &err);
409 #endif
410 
411 	srand(time(NULL));
412 
413 	exchange_rates_time[0] = 0;
414 	exchange_rates_time[1] = (time_t) 447984L * (time_t) 3600;
415 	exchange_rates_time[2] = 0;
416 	priv->exchange_rates_time2[0] = (time_t) 447984L * (time_t) 3600;
417 	exchange_rates_check_time[0] = 0;
418 	exchange_rates_check_time[1] = (time_t) 447984L * (time_t) 3600;
419 	exchange_rates_check_time[2] = 0;
420 	priv->exchange_rates_check_time2[0] = (time_t) 447984L * (time_t) 3600;
421 	b_exchange_rates_warning_enabled = true;
422 	b_exchange_rates_used = 0;
423 
424 	i_aborted = 0;
425 	b_controlled = false;
426 	i_timeout = 0;
427 
428 	setPrecision(DEFAULT_PRECISION);
429 	b_interval = true;
430 	i_stop_interval = 0;
431 	i_start_interval = 0;
432 
433 	b_var_units = true;
434 
435 	addStringAlternative(SIGN_DIVISION, DIVISION);
436 	addStringAlternative(SIGN_DIVISION_SLASH, DIVISION);
437 	addStringAlternative("⁄", DIVISION);
438 	addStringAlternative(SIGN_MULTIPLICATION, MULTIPLICATION);
439 	addStringAlternative(SIGN_MULTIDOT, MULTIPLICATION);
440 	addStringAlternative(SIGN_MIDDLEDOT, MULTIPLICATION);
441 	addStringAlternative(SIGN_MULTIBULLET, MULTIPLICATION);
442 	addStringAlternative(SIGN_SMALLCIRCLE, MULTIPLICATION);
443 	addStringAlternative(SIGN_MINUS, MINUS);
444 	addStringAlternative("–", MINUS);
445 	addStringAlternative(SIGN_PLUS, PLUS);
446 	addStringAlternative(SIGN_NOT_EQUAL, " " NOT EQUALS);
447 	addStringAlternative(SIGN_GREATER_OR_EQUAL, GREATER EQUALS);
448 	addStringAlternative(SIGN_LESS_OR_EQUAL, LESS EQUALS);
449 	addStringAlternative(";", COMMA);
450 	addStringAlternative("\t", SPACE);
451 	addStringAlternative("\n", SPACE);
452 	addStringAlternative(" ", SPACE);
453 	addStringAlternative(" ", SPACE);
454 	addStringAlternative(" ", SPACE);
455 	addStringAlternative("**", POWER);
456 	addStringAlternative("↊", "X");
457 	addStringAlternative("↋", "E");
458 	addStringAlternative("∧", BITWISE_AND);
459 	addStringAlternative("∨", BITWISE_OR);
460 	addStringAlternative("¬", BITWISE_NOT);
461 	addStringAlternative(SIGN_MICRO, "μ");
462 
463 	per_str = _("per");
464 	per_str_len = per_str.length();
465 	times_str = _("times");
466 	times_str_len = times_str.length();
467 	plus_str = _("plus");
468 	plus_str_len = plus_str.length();
469 	minus_str = _("minus");
470 	minus_str_len = minus_str.length();
471 	and_str = _("and");
472 	if(and_str == "and") and_str = "";
473 	and_str_len = and_str.length();
474 	AND_str = "AND";
475 	AND_str_len = AND_str.length();
476 	or_str = _("or");
477 	if(or_str == "or") or_str = "";
478 	or_str_len = or_str.length();
479 	OR_str = "OR";
480 	OR_str_len = OR_str.length();
481 	XOR_str = "XOR";
482 	XOR_str_len = XOR_str.length();
483 
484 	char *current_lc_numeric = setlocale(LC_NUMERIC, NULL);
485 	if(current_lc_numeric) saved_locale = strdup(current_lc_numeric);
486 	else saved_locale = NULL;
487 	struct lconv *lc = localeconv();
488 	if(!lc) {
489 		setlocale(LC_NUMERIC, "C");
490 		lc = localeconv();
491 	}
492 	place_currency_sign_before = lc->p_cs_precedes;
493 	place_currency_sign_before_negative = lc->n_cs_precedes;
494 #ifdef HAVE_STRUCT_LCONV_INT_P_CS_PRECEDES
495  	place_currency_code_before = lc->int_p_cs_precedes;
496 #else
497 	place_currency_code_before = place_currency_sign_before;
498 #endif
499 #ifdef HAVE_STRUCT_LCONV_INT_N_CS_PRECEDES
500 	place_currency_code_before_negative = lc->int_n_cs_precedes;
501 #else
502 	place_currency_code_before_negative = place_currency_sign_before_negative;
503 #endif
504 	local_digit_group_separator = lc->thousands_sep;
505 	if((local_digit_group_separator.length() == 1 && local_digit_group_separator[0] < 0) || local_digit_group_separator == " ") local_digit_group_separator = " ";
506 	else if(local_digit_group_separator == " ") local_digit_group_separator = " ";
507 	local_digit_group_format = lc->grouping;
508 	remove_blank_ends(local_digit_group_format);
509 	default_dot_as_separator = (local_digit_group_separator == ".");
510 	if(strcmp(lc->decimal_point, ",") == 0) {
511 		DOT_STR = ",";
512 		DOT_S = ".,";
513 		COMMA_STR = ";";
514 		COMMA_S = ";";
515 	} else {
516 		DOT_STR = ".";
517 		DOT_S = ".";
518 		COMMA_STR = ",";
519 		COMMA_S = ",;";
520 	}
521 	setlocale(LC_NUMERIC, "C");
522 
523 	NAME_NUMBER_PRE_S = "_#";
524 	NAME_NUMBER_PRE_STR = "_";
525 
526 	//"to"-operator
527 	string str = _("to");
528 	local_to = (str != "to");
529 
530 	decimal_null_prefix = new DecimalPrefix(0, "", "");
531 	binary_null_prefix = new BinaryPrefix(0, "", "");
532 	m_undefined.setUndefined();
533 	m_empty_vector.clearVector();
534 	m_empty_matrix.clearMatrix();
535 	m_zero.clear();
536 	m_one.set(1, 1, 0);
537 	m_minus_one.set(-1, 1, 0);
538 	nr_zero.clear();
539 	nr_one.set(1, 1, 0);
540 	nr_two.set(2, 1, 0);
541 	nr_three.set(3, 1, 0);
542 	nr_half.set(1, 2, 0);
543 	nr_minus_half.set(-1, 2, 0);
544 	nr_one_i.setImaginaryPart(1, 1, 0);
545 	nr_minus_i.setImaginaryPart(-1, 1, 0);
546 	m_one_i.set(nr_one_i);
547 	nr_minus_one.set(-1, 1, 0);
548 	nr_plus_inf.setPlusInfinity();
549 	nr_minus_inf.setMinusInfinity();
550 	no_evaluation.approximation = APPROXIMATION_EXACT;
551 	no_evaluation.structuring = STRUCTURING_NONE;
552 	no_evaluation.sync_units = false;
553 
554 	save_printoptions.decimalpoint_sign = ".";
555 	save_printoptions.comma_sign = ",";
556 	save_printoptions.use_reference_names = true;
557 	save_printoptions.preserve_precision = true;
558 	save_printoptions.interval_display = INTERVAL_DISPLAY_INTERVAL;
559 	save_printoptions.limit_implicit_multiplication = true;
560 	save_printoptions.spacious = false;
561 	save_printoptions.number_fraction_format = FRACTION_FRACTIONAL;
562 	save_printoptions.short_multiplication = false;
563 	save_printoptions.show_ending_zeroes = false;
564 	save_printoptions.use_unit_prefixes = false;
565 
566 	message_printoptions.interval_display = INTERVAL_DISPLAY_PLUSMINUS;
567 	message_printoptions.spell_out_logical_operators = true;
568 	message_printoptions.number_fraction_format = FRACTION_FRACTIONAL;
569 
570 	default_user_evaluation_options.structuring = STRUCTURING_SIMPLIFY;
571 
572 	default_assumptions = new Assumptions;
573 	default_assumptions->setType(ASSUMPTION_TYPE_REAL);
574 	default_assumptions->setSign(ASSUMPTION_SIGN_UNKNOWN);
575 
576 	u_rad = NULL; u_gra = NULL; u_deg = NULL;
577 
578 	b_save_called = false;
579 
580 	ILLEGAL_IN_NAMES = "\a\b" + DOT_S + RESERVED OPERATORS SPACES PARENTHESISS VECTOR_WRAPS COMMAS;
581 	ILLEGAL_IN_NAMES_MINUS_SPACE_STR = "\a\b" + DOT_S + RESERVED OPERATORS PARENTHESISS VECTOR_WRAPS COMMAS;
582 	ILLEGAL_IN_UNITNAMES = ILLEGAL_IN_NAMES + NUMBERS;
583 	b_argument_errors = true;
584 	current_stage = MESSAGE_STAGE_UNSET;
585 	calculator = this;
586 	srand48(time(0));
587 
588 	addBuiltinVariables();
589 	addBuiltinFunctions();
590 	addBuiltinUnits();
591 
592 	disable_errors_ref = 0;
593 	b_busy = false;
594 	b_gnuplot_open = false;
595 	gnuplot_pipe = NULL;
596 
597 	calculate_thread = new CalculateThread;
598 }
~Calculator()599 Calculator::~Calculator() {
600 	closeGnuplot();
601 	abort();
602 	terminateThreads();
603 	delete priv;
604 	delete calculate_thread;
605 	gmp_randclear(randstate);
606 #ifdef HAVE_ICU
607 	if(ucm) ucasemap_close(ucm);
608 #endif
609 }
610 
getGraUnit()611 Unit *Calculator::getGraUnit() {
612 	if(!u_gra) u_gra = getUnit("gra");
613 	if(!u_gra) {
614 		error(true, _("Gradians unit is missing. Creating one for this session."), NULL);
615 		u_gra = addUnit(new AliasUnit(_("Angle/Plane Angle"), "gra", "gradians", "gradian", "Gradian", getRadUnit(), "pi/200", 1, "", false, true, true));
616 	}
617 	return u_gra;
618 }
getRadUnit()619 Unit *Calculator::getRadUnit() {
620 	if(!u_rad) u_rad = getUnit("rad");
621 	if(!u_rad) {
622 		error(true, _("Radians unit is missing. Creating one for this session."), NULL);
623 		u_rad = addUnit(new Unit(_("Angle/Plane Angle"), "rad", "radians", "radian", "Radian", false, true, true));
624 	}
625 	return u_rad;
626 }
getDegUnit()627 Unit *Calculator::getDegUnit() {
628 	if(!u_deg) u_deg = getUnit("deg");
629 	if(!u_deg) {
630 		error(true, _("Degrees unit is missing. Creating one for this session."), NULL);
631 		u_deg = addUnit(new AliasUnit(_("Angle/Plane Angle"), "deg", "degrees", "degree", "Degree", getRadUnit(), "pi/180", 1, "", false, true, true));
632 	}
633 	return u_deg;
634 }
635 
utf8_pos_is_valid_in_name(char * pos)636 bool Calculator::utf8_pos_is_valid_in_name(char *pos) {
637 	if(is_in(ILLEGAL_IN_NAMES, pos[0])) {
638 		return false;
639 	}
640 	if((unsigned char) pos[0] >= 0xC0) {
641 		string str;
642 		str += pos[0];
643 		while((unsigned char) pos[1] >= 0x80 && (unsigned char) pos[1] < 0xC0) {
644 			str += pos[1];
645 			pos++;
646 		}
647 		return str != SIGN_DIVISION && str != SIGN_DIVISION_SLASH && str != SIGN_MULTIPLICATION && str != SIGN_MULTIDOT && str != SIGN_SMALLCIRCLE && str != SIGN_MULTIBULLET && str != SIGN_MINUS && str != SIGN_PLUS && str != SIGN_NOT_EQUAL && str != SIGN_GREATER_OR_EQUAL && str != SIGN_LESS_OR_EQUAL;
648 	}
649 	return true;
650 }
651 
showArgumentErrors() const652 bool Calculator::showArgumentErrors() const {
653 	return b_argument_errors;
654 }
beginTemporaryStopMessages()655 void Calculator::beginTemporaryStopMessages() {
656 	disable_errors_ref++;
657 	stopped_errors_count.push_back(0);
658 	stopped_warnings_count.push_back(0);
659 	stopped_messages_count.push_back(0);
660 	vector<CalculatorMessage> vcm;
661 	stopped_messages.push_back(vcm);
662 }
endTemporaryStopMessages(int * message_count,int * warning_count,int release_messages_if_no_equal_or_greater_than_message_type)663 int Calculator::endTemporaryStopMessages(int *message_count, int *warning_count, int release_messages_if_no_equal_or_greater_than_message_type) {
664 	if(disable_errors_ref <= 0) return -1;
665 	disable_errors_ref--;
666 	int ret = stopped_errors_count[disable_errors_ref];
667 	bool release_messages = false;
668 	if(release_messages_if_no_equal_or_greater_than_message_type >= MESSAGE_INFORMATION) {
669 		if(ret > 0) release_messages = true;
670 		if(release_messages_if_no_equal_or_greater_than_message_type == MESSAGE_WARNING && stopped_warnings_count[disable_errors_ref] > 0) release_messages = true;
671 		else if(release_messages_if_no_equal_or_greater_than_message_type == MESSAGE_INFORMATION && stopped_messages_count[disable_errors_ref] > 0) release_messages = true;
672 	}
673 	if(message_count) *message_count = stopped_messages_count[disable_errors_ref];
674 	if(warning_count) *warning_count = stopped_warnings_count[disable_errors_ref];
675 	stopped_errors_count.pop_back();
676 	stopped_warnings_count.pop_back();
677 	stopped_messages_count.pop_back();
678 	if(release_messages) addMessages(&stopped_messages[disable_errors_ref]);
679 	stopped_messages.pop_back();
680 	return ret;
681 }
endTemporaryStopMessages(bool release_messages,vector<CalculatorMessage> * blocked_messages)682 void Calculator::endTemporaryStopMessages(bool release_messages, vector<CalculatorMessage> *blocked_messages) {
683 	if(disable_errors_ref <= 0) return;
684 	disable_errors_ref--;
685 	stopped_errors_count.pop_back();
686 	stopped_warnings_count.pop_back();
687 	stopped_messages_count.pop_back();
688 	if(blocked_messages) *blocked_messages = stopped_messages[disable_errors_ref];
689 	if(release_messages) addMessages(&stopped_messages[disable_errors_ref]);
690 	stopped_messages.pop_back();
691 }
addMessages(vector<CalculatorMessage> * message_vector)692 void Calculator::addMessages(vector<CalculatorMessage> *message_vector) {
693 	for(size_t i3 = 0; i3 < message_vector->size(); i3++) {
694 		string error_str = (*message_vector)[i3].message();
695 		bool dup_error = false;
696 		for(size_t i = 0; i < messages.size(); i++) {
697 			if(error_str == messages[i].message()) {
698 				dup_error = true;
699 				break;
700 			}
701 		}
702 		if(!dup_error) {
703 			if(disable_errors_ref > 0) {
704 				for(size_t i2 = 0; !dup_error && i2 < (size_t) disable_errors_ref; i2++) {
705 					for(size_t i = 0; i < stopped_messages[i2].size(); i++) {
706 						if(error_str == stopped_messages[i2][i].message()) {
707 							dup_error = true;
708 							break;
709 						}
710 					}
711 				}
712 				if(!dup_error) stopped_messages[disable_errors_ref - 1].push_back((*message_vector)[i3]);
713 			} else {
714 				messages.push_back((*message_vector)[i3]);
715 			}
716 		}
717 	}
718 }
messagePrintOptions() const719 const PrintOptions &Calculator::messagePrintOptions() const {return message_printoptions;}
setMessagePrintOptions(const PrintOptions & po)720 void Calculator::setMessagePrintOptions(const PrintOptions &po) {message_printoptions = po;}
721 
getVariable(size_t index) const722 Variable *Calculator::getVariable(size_t index) const {
723 	if(index < variables.size()) {
724 		return variables[index];
725 	}
726 	return NULL;
727 }
hasVariable(Variable * v)728 bool Calculator::hasVariable(Variable *v) {
729 	for(size_t i = 0; i < variables.size(); i++) {
730 		if(variables[i] == v) return true;
731 	}
732 	return false;
733 }
hasUnit(Unit * u)734 bool Calculator::hasUnit(Unit *u) {
735 	for(size_t i = 0; i < units.size(); i++) {
736 		if(units[i] == u) return true;
737 	}
738 	return false;
739 }
hasFunction(MathFunction * f)740 bool Calculator::hasFunction(MathFunction *f) {
741 	for(size_t i = 0; i < functions.size(); i++) {
742 		if(functions[i] == f) return true;
743 	}
744 	return false;
745 }
stillHasVariable(Variable * v)746 bool Calculator::stillHasVariable(Variable *v) {
747 	for(vector<Variable*>::iterator it = deleted_variables.begin(); it != deleted_variables.end(); ++it) {
748 		if(*it == v) return false;
749 	}
750 	return true;
751 }
stillHasUnit(Unit * u)752 bool Calculator::stillHasUnit(Unit *u) {
753 	for(vector<Unit*>::iterator it = deleted_units.begin(); it != deleted_units.end(); ++it) {
754 		if(*it == u) return false;
755 	}
756 	return true;
757 }
stillHasFunction(MathFunction * f)758 bool Calculator::stillHasFunction(MathFunction *f) {
759 	for(vector<MathFunction*>::iterator it = deleted_functions.begin(); it != deleted_functions.end(); ++it) {
760 		if(*it == f) return false;
761 	}
762 	return true;
763 }
saveFunctionCalled()764 void Calculator::saveFunctionCalled() {
765 	b_save_called = true;
766 }
checkSaveFunctionCalled()767 bool Calculator::checkSaveFunctionCalled() {
768 	if(b_save_called) {
769 		b_save_called = false;
770 		return true;
771 	}
772 	return false;
773 }
getActiveExpressionItem(ExpressionItem * item)774 ExpressionItem *Calculator::getActiveExpressionItem(ExpressionItem *item) {
775 	if(!item) return NULL;
776 	for(size_t i = 1; i <= item->countNames(); i++) {
777 		ExpressionItem *item2 = getActiveExpressionItem(item->getName(i).name, item);
778 		if(item2) {
779 			return item2;
780 		}
781 	}
782 	return NULL;
783 }
getActiveExpressionItem(string name,ExpressionItem * item)784 ExpressionItem *Calculator::getActiveExpressionItem(string name, ExpressionItem *item) {
785 	if(name.empty()) return NULL;
786 	for(size_t index = 0; index < variables.size(); index++) {
787 		if(variables[index] != item && variables[index]->isActive() && variables[index]->hasName(name)) {
788 			return variables[index];
789 		}
790 	}
791 	for(size_t index = 0; index < functions.size(); index++) {
792 		if(functions[index] != item && functions[index]->isActive() && functions[index]->hasName(name)) {
793 			return functions[index];
794 		}
795 	}
796 	for(size_t i = 0; i < units.size(); i++) {
797 		if(units[i] != item && units[i]->isActive() && units[i]->hasName(name)) {
798 			return units[i];
799 		}
800 	}
801 	return NULL;
802 }
getInactiveExpressionItem(string name,ExpressionItem * item)803 ExpressionItem *Calculator::getInactiveExpressionItem(string name, ExpressionItem *item) {
804 	if(name.empty()) return NULL;
805 	for(size_t index = 0; index < variables.size(); index++) {
806 		if(variables[index] != item && !variables[index]->isActive() && variables[index]->hasName(name)) {
807 			return variables[index];
808 		}
809 	}
810 	for(size_t index = 0; index < functions.size(); index++) {
811 		if(functions[index] != item && !functions[index]->isActive() && functions[index]->hasName(name)) {
812 			return functions[index];
813 		}
814 	}
815 	for(size_t i = 0; i < units.size(); i++) {
816 		if(units[i] != item && !units[i]->isActive() && units[i]->hasName(name)) {
817 			return units[i];
818 		}
819 	}
820 	return NULL;
821 }
getExpressionItem(string name,ExpressionItem * item)822 ExpressionItem *Calculator::getExpressionItem(string name, ExpressionItem *item) {
823 	if(name.empty()) return NULL;
824 	Variable *v = getVariable(name);
825 	if(v && v != item) return v;
826 	MathFunction *f = getFunction(name);
827 	if(f && f != item) return f;
828 	Unit *u = getUnit(name);
829 	if(u && u != item) return u;
830 	u = getCompositeUnit(name);
831 	if(u && u != item) return u;
832 	return NULL;
833 }
getUnit(size_t index) const834 Unit *Calculator::getUnit(size_t index) const {
835 	if(index < units.size()) {
836 		return units[index];
837 	}
838 	return NULL;
839 }
getFunction(size_t index) const840 MathFunction *Calculator::getFunction(size_t index) const {
841 	if(index < functions.size()) {
842 		return functions[index];
843 	}
844 	return NULL;
845 }
846 
setDefaultAssumptions(Assumptions * ass)847 void Calculator::setDefaultAssumptions(Assumptions *ass) {
848 	if(default_assumptions) delete default_assumptions;
849 	default_assumptions = ass;
850 }
defaultAssumptions()851 Assumptions *Calculator::defaultAssumptions() {
852 	return default_assumptions;
853 }
854 
getPrefix(size_t index) const855 Prefix *Calculator::getPrefix(size_t index) const {
856 	if(index < prefixes.size()) {
857 		return prefixes[index];
858 	}
859 	return NULL;
860 }
getPrefix(string name_) const861 Prefix *Calculator::getPrefix(string name_) const {
862 	for(size_t i = 0; i < prefixes.size(); i++) {
863 		if(prefixes[i]->shortName(false) == name_ || prefixes[i]->longName(false) == name_ || prefixes[i]->unicodeName(false) == name_) {
864 			return prefixes[i];
865 		}
866 	}
867 	return NULL;
868 }
getDecimalNullPrefix() const869 Prefix *Calculator::getDecimalNullPrefix() const {return decimal_null_prefix;}
getBinaryNullPrefix() const870 Prefix *Calculator::getBinaryNullPrefix() const {return binary_null_prefix;}
getExactDecimalPrefix(int exp10,int exp) const871 DecimalPrefix *Calculator::getExactDecimalPrefix(int exp10, int exp) const {
872 	for(size_t i = 0; i < decimal_prefixes.size(); i++) {
873 		if(decimal_prefixes[i]->exponent(exp) == exp10) {
874 			return decimal_prefixes[i];
875 		} else if(decimal_prefixes[i]->exponent(exp) > exp10) {
876 			break;
877 		}
878 	}
879 	return NULL;
880 }
getExactBinaryPrefix(int exp2,int exp) const881 BinaryPrefix *Calculator::getExactBinaryPrefix(int exp2, int exp) const {
882 	for(size_t i = 0; i < binary_prefixes.size(); i++) {
883 		if(binary_prefixes[i]->exponent(exp) == exp2) {
884 			return binary_prefixes[i];
885 		} else if(binary_prefixes[i]->exponent(exp) > exp2) {
886 			break;
887 		}
888 	}
889 	return NULL;
890 }
getExactPrefix(const Number & o,int exp) const891 Prefix *Calculator::getExactPrefix(const Number &o, int exp) const {
892 	ComparisonResult c;
893 	for(size_t i = 0; i < prefixes.size(); i++) {
894 		c = o.compare(prefixes[i]->value(exp));
895 		if(c == COMPARISON_RESULT_EQUAL) {
896 			return prefixes[i];
897 		} else if(c == COMPARISON_RESULT_GREATER) {
898 			break;
899 		}
900 	}
901 	return NULL;
902 }
getNearestDecimalPrefix(int exp10,int exp) const903 DecimalPrefix *Calculator::getNearestDecimalPrefix(int exp10, int exp) const {
904 	if(decimal_prefixes.size() <= 0) return NULL;
905 	int i = 0;
906 	if(exp < 0) {
907 		i = decimal_prefixes.size() - 1;
908 	}
909 	while((exp < 0 && i >= 0) || (exp >= 0 && i < (int) decimal_prefixes.size())) {
910 		if(decimal_prefixes[i]->exponent(exp) == exp10) {
911 			return decimal_prefixes[i];
912 		} else if(decimal_prefixes[i]->exponent(exp) > exp10) {
913 			if(i == 0) {
914 				return decimal_prefixes[i];
915 			} else if(exp10 - decimal_prefixes[i - 1]->exponent(exp) < decimal_prefixes[i]->exponent(exp) - exp10) {
916 				return decimal_prefixes[i - 1];
917 			} else {
918 				return decimal_prefixes[i];
919 			}
920 		}
921 		if(exp < 0) {
922 			i--;
923 		} else {
924 			i++;
925 		}
926 	}
927 	return decimal_prefixes[decimal_prefixes.size() - 1];
928 }
getOptimalDecimalPrefix(int exp10,int exp,bool all_prefixes) const929 DecimalPrefix *Calculator::getOptimalDecimalPrefix(int exp10, int exp, bool all_prefixes) const {
930 	if(decimal_prefixes.size() <= 0 || exp10 == 0) return NULL;
931 	int i = 0;
932 	if(exp < 0) {
933 		i = decimal_prefixes.size() - 1;
934 	}
935 	DecimalPrefix *p = NULL, *p_prev = NULL;
936 	int exp10_1, exp10_2;
937 	while((exp < 0 && i >= 0) || (exp >= 0 && i < (int) decimal_prefixes.size())) {
938 		if(all_prefixes || decimal_prefixes[i]->exponent() % 3 == 0) {
939 			p = decimal_prefixes[i];
940 			if(p_prev && (p_prev->exponent() >= 0) != (p->exponent() >= 0) && p_prev->exponent() != 0) {
941 				if(exp < 0) {
942 					i++;
943 				} else {
944 					i--;
945 				}
946 				p = decimal_null_prefix;
947 			}
948 			if(p->exponent(exp) == exp10) {
949 				if(p == decimal_null_prefix) return NULL;
950 				return p;
951 			} else if(p->exponent(exp) > exp10) {
952 				if(i == 0) {
953 					if(p == decimal_null_prefix) return NULL;
954 					return p;
955 				}
956 				exp10_1 = exp10;
957 				if(p_prev) {
958 					exp10_1 -= p_prev->exponent(exp);
959 				}
960 				exp10_2 = p->exponent(exp);
961 				exp10_2 -= exp10;
962 				exp10_2 *= 2;
963 				exp10_2 += 2;
964 				if(exp10_1 < exp10_2) {
965 					if(p_prev == decimal_null_prefix) return NULL;
966 					return p_prev;
967 				} else {
968 					return p;
969 				}
970 			}
971 			p_prev = p;
972 		}
973 		if(exp < 0) {
974 			i--;
975 		} else {
976 			i++;
977 		}
978 	}
979 	return p_prev;
980 }
getOptimalDecimalPrefix(const Number & exp10,const Number & exp,bool all_prefixes) const981 DecimalPrefix *Calculator::getOptimalDecimalPrefix(const Number &exp10, const Number &exp, bool all_prefixes) const {
982 	if(decimal_prefixes.size() <= 0 || exp10.isZero()) return NULL;
983 	int i = 0;
984 	ComparisonResult c;
985 	if(exp.isNegative()) {
986 		i = decimal_prefixes.size() - 1;
987 	}
988 	DecimalPrefix *p = NULL, *p_prev = NULL;
989 	Number exp10_1, exp10_2;
990 	while((exp.isNegative() && i >= 0) || (!exp.isNegative() && i < (int) decimal_prefixes.size())) {
991 		if(all_prefixes || decimal_prefixes[i]->exponent() % 3 == 0) {
992 			p = decimal_prefixes[i];
993 			if(p_prev && (p_prev->exponent() >= 0) != (p->exponent() >= 0) && p_prev->exponent() != 0) {
994 				if(exp.isNegative()) {
995 					i++;
996 				} else {
997 					i--;
998 				}
999 				p = decimal_null_prefix;
1000 			}
1001 			c = exp10.compare(p->exponent(exp));
1002 			if(c == COMPARISON_RESULT_EQUAL) {
1003 				if(p == decimal_null_prefix) return NULL;
1004 				return p;
1005 			} else if(c == COMPARISON_RESULT_GREATER) {
1006 				if(i == 0) {
1007 					if(p == decimal_null_prefix) return NULL;
1008 					return p;
1009 				}
1010 				exp10_1 = exp10;
1011 				if(p_prev) {
1012 					exp10_1 -= p_prev->exponent(exp);
1013 				}
1014 				exp10_2 = p->exponent(exp);
1015 				exp10_2 -= exp10;
1016 				exp10_2 *= 2;
1017 				exp10_2 += 2;
1018 				if(exp10_1.isLessThan(exp10_2)) {
1019 					if(p_prev == decimal_null_prefix) return NULL;
1020 					return p_prev;
1021 				} else {
1022 					return p;
1023 				}
1024 			}
1025 			p_prev = p;
1026 		}
1027 		if(exp.isNegative()) {
1028 			i--;
1029 		} else {
1030 			i++;
1031 		}
1032 	}
1033 	return p_prev;
1034 }
setTemperatureCalculationMode(TemperatureCalculationMode temperature_calculation_mode)1035 void Calculator::setTemperatureCalculationMode(TemperatureCalculationMode temperature_calculation_mode) {
1036 	priv->temperature_calculation = temperature_calculation_mode;
1037 }
getTemperatureCalculationMode() const1038 TemperatureCalculationMode Calculator::getTemperatureCalculationMode() const {
1039 	return priv->temperature_calculation;
1040 }
usesBinaryPrefixes() const1041 int Calculator::usesBinaryPrefixes() const {
1042 	return priv->use_binary_prefixes;
1043 }
useBinaryPrefixes(int use_binary_prefixes)1044 void Calculator::useBinaryPrefixes(int use_binary_prefixes) {
1045 	priv->use_binary_prefixes = use_binary_prefixes;
1046 }
getNearestBinaryPrefix(int exp2,int exp) const1047 BinaryPrefix *Calculator::getNearestBinaryPrefix(int exp2, int exp) const {
1048 	if(binary_prefixes.size() <= 0) return NULL;
1049 	int i = 0;
1050 	if(exp < 0) {
1051 		i = binary_prefixes.size() - 1;
1052 	}
1053 	while((exp < 0 && i >= 0) || (exp >= 0 && i < (int) binary_prefixes.size())) {
1054 		if(binary_prefixes[i]->exponent(exp) == exp2) {
1055 			return binary_prefixes[i];
1056 		} else if(binary_prefixes[i]->exponent(exp) > exp2) {
1057 			if(i == 0) {
1058 				return binary_prefixes[i];
1059 			} else if(exp2 - binary_prefixes[i - 1]->exponent(exp) < binary_prefixes[i]->exponent(exp) - exp2) {
1060 				return binary_prefixes[i - 1];
1061 			} else {
1062 				return binary_prefixes[i];
1063 			}
1064 		}
1065 		if(exp < 0) {
1066 			i--;
1067 		} else {
1068 			i++;
1069 		}
1070 	}
1071 	return binary_prefixes[binary_prefixes.size() - 1];
1072 }
getOptimalBinaryPrefix(int exp2,int exp) const1073 BinaryPrefix *Calculator::getOptimalBinaryPrefix(int exp2, int exp) const {
1074 	if(binary_prefixes.size() <= 0 || exp2 == 0) return NULL;
1075 	int i = -1;
1076 	if(exp < 0) {
1077 		i = binary_prefixes.size() - 1;
1078 	}
1079 	BinaryPrefix *p = NULL, *p_prev = NULL;
1080 	int exp2_1, exp2_2;
1081 	while((exp < 0 && i >= -1) || (exp >= 0 && i < (int) binary_prefixes.size())) {
1082 		if(i >= 0) p = binary_prefixes[i];
1083 		else p = binary_null_prefix;
1084 		if(p_prev && (p_prev->exponent() >= 0) != (p->exponent() >= 0) && p_prev->exponent() != 0) {
1085 			if(exp < 0) {
1086 				i++;
1087 			} else {
1088 				i--;
1089 			}
1090 			p = binary_null_prefix;
1091 		}
1092 		if(p->exponent(exp) == exp2) {
1093 			if(p == binary_null_prefix) return NULL;
1094 			return p;
1095 		} else if(p->exponent(exp) > exp2) {
1096 			exp2_1 = exp2;
1097 			if(p_prev) {
1098 				exp2_1 -= p_prev->exponent(exp);
1099 			}
1100 			exp2_2 = p->exponent(exp);
1101 			exp2_2 -= exp2;
1102 			exp2_2 += 9;
1103 			if(exp2_1 < exp2_2) {
1104 				if(p_prev == binary_null_prefix) return NULL;
1105 				return p_prev;
1106 			} else {
1107 				return p;
1108 			}
1109 		}
1110 		p_prev = p;
1111 		if(exp < 0) {
1112 			i--;
1113 		} else {
1114 			i++;
1115 		}
1116 	}
1117 	return p_prev;
1118 }
getOptimalBinaryPrefix(const Number & exp2,const Number & exp) const1119 BinaryPrefix *Calculator::getOptimalBinaryPrefix(const Number &exp2, const Number &exp) const {
1120 	if(binary_prefixes.size() <= 0 || exp2.isZero()) return NULL;
1121 	int i = -1;
1122 	ComparisonResult c;
1123 	if(exp.isNegative()) {
1124 		i = binary_prefixes.size() - 1;
1125 	}
1126 	BinaryPrefix *p = NULL, *p_prev = NULL;
1127 	Number exp2_1, exp2_2;
1128 	while((exp.isNegative() && i >= -1) || (!exp.isNegative() && i < (int) binary_prefixes.size())) {
1129 		if(i >= 0) p = binary_prefixes[i];
1130 		else p = binary_null_prefix;
1131 		c = exp2.compare(p->exponent(exp));
1132 		if(c == COMPARISON_RESULT_EQUAL) {
1133 			if(p == binary_null_prefix) return NULL;
1134 			return p;
1135 		} else if(c == COMPARISON_RESULT_GREATER) {
1136 			exp2_1 = exp2;
1137 			if(p_prev) {
1138 				exp2_1 -= p_prev->exponent(exp);
1139 			}
1140 			exp2_2 = p->exponent(exp);
1141 			exp2_2 -= exp2;
1142 			exp2_2 += 9;
1143 			if(exp2_1.isLessThan(exp2_2)) {
1144 				if(p_prev == binary_null_prefix) return NULL;
1145 				return p_prev;
1146 			} else {
1147 				return p;
1148 			}
1149 		}
1150 		p_prev = p;
1151 		if(exp.isNegative()) {
1152 			i--;
1153 		} else {
1154 			i++;
1155 		}
1156 	}
1157 	return p_prev;
1158 }
addPrefix(Prefix * p)1159 Prefix *Calculator::addPrefix(Prefix *p) {
1160 	if(p->type() == PREFIX_DECIMAL) {
1161 		decimal_prefixes.push_back((DecimalPrefix*) p);
1162 	} else if(p->type() == PREFIX_BINARY) {
1163 		binary_prefixes.push_back((BinaryPrefix*) p);
1164 	}
1165 	prefixes.push_back(p);
1166 	prefixNameChanged(p, true);
1167 	return p;
1168 }
prefixNameChanged(Prefix * p,bool new_item)1169 void Calculator::prefixNameChanged(Prefix *p, bool new_item) {
1170 	size_t l2;
1171 	if(!new_item) delPrefixUFV(p);
1172 	if(!p->longName(false).empty()) {
1173 		l2 = p->longName(false).length();
1174 		if(l2 > UFV_LENGTHS) {
1175 			size_t i = 0, l;
1176 			for(vector<void*>::iterator it = ufvl.begin(); ; ++it) {
1177 				l = 0;
1178 				if(it != ufvl.end()) {
1179 					if(ufvl_t[i] == 'v')
1180 						l = ((Variable*) (*it))->getName(ufvl_i[i]).name.length();
1181 					else if(ufvl_t[i] == 'f')
1182 						l = ((MathFunction*) (*it))->getName(ufvl_i[i]).name.length();
1183 					else if(ufvl_t[i] == 'u')
1184 						l = ((Unit*) (*it))->getName(ufvl_i[i]).name.length();
1185 					else if(ufvl_t[i] == 'p')
1186 						l = ((Prefix*) (*it))->shortName(false).length();
1187 					else if(ufvl_t[i] == 'P')
1188 						l = ((Prefix*) (*it))->longName(false).length();
1189 					else if(ufvl_t[i] == 'q')
1190 						l = ((Prefix*) (*it))->unicodeName(false).length();
1191 				}
1192 				if(it == ufvl.end()) {
1193 					ufvl.push_back((void*) p);
1194 					ufvl_t.push_back('P');
1195 					ufvl_i.push_back(1);
1196 					break;
1197 				} else if(l <= l2) {
1198 					ufvl.insert(it, (void*) p);
1199 					ufvl_t.insert(ufvl_t.begin() + i, 'P');
1200 					ufvl_i.insert(ufvl_i.begin() + i, 1);
1201 					break;
1202 				}
1203 				i++;
1204 			}
1205 		} else if(l2 > 0) {
1206 			l2--;
1207 			ufv[0][l2].push_back((void*) p);
1208 			ufv_i[0][l2].push_back(1);
1209 		}
1210 	}
1211 	if(!p->shortName(false).empty()) {
1212 		l2 = p->shortName(false).length();
1213 		if(l2 > UFV_LENGTHS) {
1214 			size_t i = 0, l;
1215 			for(vector<void*>::iterator it = ufvl.begin(); ; ++it) {
1216 				l = 0;
1217 				if(it != ufvl.end()) {
1218 					if(ufvl_t[i] == 'v')
1219 						l = ((Variable*) (*it))->getName(ufvl_i[i]).name.length();
1220 					else if(ufvl_t[i] == 'f')
1221 						l = ((MathFunction*) (*it))->getName(ufvl_i[i]).name.length();
1222 					else if(ufvl_t[i] == 'u')
1223 						l = ((Unit*) (*it))->getName(ufvl_i[i]).name.length();
1224 					else if(ufvl_t[i] == 'p')
1225 						l = ((Prefix*) (*it))->shortName(false).length();
1226 					else if(ufvl_t[i] == 'P')
1227 						l = ((Prefix*) (*it))->longName(false).length();
1228 					else if(ufvl_t[i] == 'q')
1229 						l = ((Prefix*) (*it))->unicodeName(false).length();
1230 				}
1231 				if(it == ufvl.end()) {
1232 					ufvl.push_back((void*) p);
1233 					ufvl_t.push_back('p');
1234 					ufvl_i.push_back(1);
1235 					break;
1236 				} else if(l <= l2) {
1237 					ufvl.insert(it, (void*) p);
1238 					ufvl_t.insert(ufvl_t.begin() + i, 'p');
1239 					ufvl_i.insert(ufvl_i.begin() + i, 1);
1240 					break;
1241 				}
1242 				i++;
1243 			}
1244 		} else if(l2 > 0) {
1245 			l2--;
1246 			ufv[0][l2].push_back((void*) p);
1247 			ufv_i[0][l2].push_back(2);
1248 		}
1249 	}
1250 	if(!p->unicodeName(false).empty()) {
1251 		l2 = p->unicodeName(false).length();
1252 		if(l2 > UFV_LENGTHS) {
1253 			size_t i = 0, l;
1254 			for(vector<void*>::iterator it = ufvl.begin(); ; ++it) {
1255 				l = 0;
1256 				if(it != ufvl.end()) {
1257 					if(ufvl_t[i] == 'v')
1258 						l = ((Variable*) (*it))->getName(ufvl_i[i]).name.length();
1259 					else if(ufvl_t[i] == 'f')
1260 						l = ((MathFunction*) (*it))->getName(ufvl_i[i]).name.length();
1261 					else if(ufvl_t[i] == 'u')
1262 						l = ((Unit*) (*it))->getName(ufvl_i[i]).name.length();
1263 					else if(ufvl_t[i] == 'p')
1264 						l = ((Prefix*) (*it))->shortName(false).length();
1265 					else if(ufvl_t[i] == 'P')
1266 						l = ((Prefix*) (*it))->longName(false).length();
1267 					else if(ufvl_t[i] == 'q')
1268 						l = ((Prefix*) (*it))->unicodeName(false).length();
1269 				}
1270 				if(it == ufvl.end()) {
1271 					ufvl.push_back((void*) p);
1272 					ufvl_t.push_back('q');
1273 					ufvl_i.push_back(1);
1274 					break;
1275 				} else if(l <= l2) {
1276 					ufvl.insert(it, (void*) p);
1277 					ufvl_t.insert(ufvl_t.begin() + i, 'q');
1278 					ufvl_i.insert(ufvl_i.begin() + i, 1);
1279 					break;
1280 				}
1281 				i++;
1282 			}
1283 		} else if(l2 > 0) {
1284 			l2--;
1285 			ufv[0][l2].push_back((void*) p);
1286 			ufv_i[0][l2].push_back(3);
1287 		}
1288 	}
1289 }
1290 #define PRECISION_TO_BITS(p) (((p) * 3.322) + 100)
setPrecision(int precision)1291 void Calculator::setPrecision(int precision) {
1292 	if(precision <= 0) precision = DEFAULT_PRECISION;
1293 	i_precision = precision;
1294 	mpfr_set_default_prec(PRECISION_TO_BITS(i_precision));
1295 }
getPrecision() const1296 int Calculator::getPrecision() const {
1297 	return i_precision;
1298 }
useIntervalArithmetic(bool use_interval_arithmetic)1299 void Calculator::useIntervalArithmetic(bool use_interval_arithmetic) {b_interval = use_interval_arithmetic;}
usesIntervalArithmetic() const1300 bool Calculator::usesIntervalArithmetic() const {return i_start_interval > 0 || (b_interval && i_stop_interval <= 0);}
beginTemporaryStopIntervalArithmetic()1301 void Calculator::beginTemporaryStopIntervalArithmetic() {
1302 	i_stop_interval++;
1303 }
endTemporaryStopIntervalArithmetic()1304 void Calculator::endTemporaryStopIntervalArithmetic() {
1305 	i_stop_interval--;
1306 }
beginTemporaryEnableIntervalArithmetic()1307 void Calculator::beginTemporaryEnableIntervalArithmetic() {
1308 	i_start_interval++;
1309 }
endTemporaryEnableIntervalArithmetic()1310 void Calculator::endTemporaryEnableIntervalArithmetic() {
1311 	i_start_interval--;
1312 }
1313 
setCustomInputBase(Number nr)1314 void Calculator::setCustomInputBase(Number nr) {
1315 	priv->custom_input_base = nr;
1316 	if(!nr.isReal()) {
1317 		priv->custom_input_base_i = LONG_MAX;
1318 	} else {
1319 		nr.abs(); nr.intervalToMidValue(); nr.ceil();
1320 		priv->custom_input_base_i = nr.lintValue();
1321 		if(priv->custom_input_base_i < 2) priv->custom_input_base_i = 2;
1322 	}
1323 }
setCustomOutputBase(Number nr)1324 void Calculator::setCustomOutputBase(Number nr) {priv->custom_output_base = nr;}
customInputBase() const1325 const Number &Calculator::customInputBase() const {return priv->custom_input_base;}
customOutputBase() const1326 const Number &Calculator::customOutputBase() const {return priv->custom_output_base;}
1327 
getDecimalPoint() const1328 const string &Calculator::getDecimalPoint() const {return DOT_STR;}
getComma() const1329 const string &Calculator::getComma() const {return COMMA_STR;}
localToString(bool include_spaces) const1330 string Calculator::localToString(bool include_spaces) const {
1331 	if(include_spaces) return string(SPACE) + string(_("to")) + SPACE;
1332 	else return _("to");
1333 }
localWhereString() const1334 string Calculator::localWhereString() const {
1335 	return string(SPACE) + string(_("where")) + SPACE;
1336 }
setLocale()1337 void Calculator::setLocale() {
1338 	if(b_ignore_locale) return;
1339 	if(saved_locale) setlocale(LC_NUMERIC, saved_locale);
1340 	lconv *locale = localeconv();
1341 	if(strcmp(locale->decimal_point, ",") == 0) {
1342 		DOT_STR = ",";
1343 		DOT_S = ".,";
1344 		COMMA_STR = ";";
1345 		COMMA_S = ";";
1346 	} else {
1347 		DOT_STR = ".";
1348 		DOT_S = ".";
1349 		COMMA_STR = ",";
1350 		COMMA_S = ",;";
1351 	}
1352 	setlocale(LC_NUMERIC, "C");
1353 }
setIgnoreLocale()1354 void Calculator::setIgnoreLocale() {
1355 	if(saved_locale) {
1356 		free(saved_locale);
1357 		saved_locale = NULL;
1358 	}
1359 	char *current_lc_monetary = setlocale(LC_MONETARY, NULL);
1360 	if(current_lc_monetary) saved_locale = strdup(current_lc_monetary);
1361 	else saved_locale = NULL;
1362 	setlocale(LC_ALL, "C");
1363 #ifdef ENABLE_NLS
1364 #	ifdef _WIN32
1365 	bindtextdomain(GETTEXT_PACKAGE, "NULL");
1366 	bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
1367 #	endif
1368 #endif
1369 	if(saved_locale) {
1370 		setlocale(LC_MONETARY, saved_locale);
1371 		free(saved_locale);
1372 		saved_locale = NULL;
1373 	}
1374 	b_ignore_locale = true;
1375 	per_str = "per";
1376 	per_str_len = per_str.length();
1377 	times_str = "times";
1378 	times_str_len = times_str.length();
1379 	plus_str = "plus";
1380 	plus_str_len = plus_str.length();
1381 	minus_str = "minus";
1382 	minus_str_len = minus_str.length();
1383 	and_str = "";
1384 	and_str_len = 0;
1385 	or_str = "";
1386 	or_str_len = 0;
1387 	local_to = false;
1388 	unsetLocale();
1389 }
getIgnoreLocale()1390 bool Calculator::getIgnoreLocale() {
1391 	return b_ignore_locale;
1392 }
useDecimalComma()1393 void Calculator::useDecimalComma() {
1394 	DOT_STR = ",";
1395 	DOT_S = ".,";
1396 	COMMA_STR = ";";
1397 	COMMA_S = ";";
1398 }
useDecimalPoint(bool use_comma_as_separator)1399 void Calculator::useDecimalPoint(bool use_comma_as_separator) {
1400 	DOT_STR = ".";
1401 	DOT_S = ".";
1402 	if(use_comma_as_separator) {
1403 		COMMA_STR = ";";
1404 		COMMA_S = ";";
1405 	} else {
1406 		COMMA_STR = ",";
1407 		COMMA_S = ",;";
1408 	}
1409 }
unsetLocale()1410 void Calculator::unsetLocale() {
1411 	COMMA_STR = ",";
1412 	COMMA_S = ",;";
1413 	DOT_STR = ".";
1414 	DOT_S = ".";
1415 }
1416 
resetVariables()1417 void Calculator::resetVariables() {
1418 	variables.clear();
1419 	addBuiltinVariables();
1420 }
resetFunctions()1421 void Calculator::resetFunctions() {
1422 	functions.clear();
1423 	addBuiltinFunctions();
1424 }
resetUnits()1425 void Calculator::resetUnits() {
1426 	units.clear();
1427 	addBuiltinUnits();
1428 }
reset()1429 void Calculator::reset() {
1430 	resetVariables();
1431 	resetFunctions();
1432 	resetUnits();
1433 }
1434 
addBuiltinVariables()1435 void Calculator::addBuiltinVariables() {
1436 
1437 	v_e = (KnownVariable*) addVariable(new EVariable());
1438 	v_pi = (KnownVariable*) addVariable(new PiVariable());
1439 	Number nr(1, 1);
1440 	MathStructure mstruct;
1441 	mstruct.number().setImaginaryPart(nr);
1442 	v_i = (KnownVariable*) addVariable(new KnownVariable("", "i", mstruct, "Imaginary i (sqrt(-1))", false, true));
1443 	mstruct.number().setPlusInfinity();
1444 	v_pinf = (KnownVariable*) addVariable(new KnownVariable("", "plus_infinity", mstruct, "+Infinity", false, true));
1445 	mstruct.number().setMinusInfinity();
1446 	v_minf = (KnownVariable*) addVariable(new KnownVariable("", "minus_infinity", mstruct, "-Infinity", false, true));
1447 	mstruct.setUndefined();
1448 	v_undef = (KnownVariable*) addVariable(new KnownVariable("", "undefined", mstruct, "Undefined", false, true));
1449 	v_euler = (KnownVariable*) addVariable(new EulerVariable());
1450 	v_catalan = (KnownVariable*) addVariable(new CatalanVariable());
1451 	v_precision = (KnownVariable*) addVariable(new PrecisionVariable());
1452 	v_percent = (KnownVariable*) addVariable(new KnownVariable("", "percent", MathStructure(1, 1, -2), "Percent", false, true));
1453 	v_percent->addName("%");
1454 	v_permille = (KnownVariable*) addVariable(new KnownVariable("", "permille", MathStructure(1, 1, -3), "Per Mille", false, true));
1455 	v_permyriad = (KnownVariable*) addVariable(new KnownVariable("", "permyriad", MathStructure(1, 1, -4), "Per Myriad", false, true));
1456 	v_x = (UnknownVariable*) addVariable(new UnknownVariable("", "x", "", false, false));
1457 	v_y = (UnknownVariable*) addVariable(new UnknownVariable("", "y", "", false, false));
1458 	v_z = (UnknownVariable*) addVariable(new UnknownVariable("", "z", "", false, false));
1459 	v_C = new UnknownVariable("", "C", "", false, true);
1460 	v_C->setAssumptions(new Assumptions());
1461 	v_n = (UnknownVariable*) addVariable(new UnknownVariable("", "n", "", false, true));
1462 	v_n->setAssumptions(new Assumptions());
1463 	v_n->assumptions()->setType(ASSUMPTION_TYPE_INTEGER);
1464 	v_today = (KnownVariable*) addVariable(new TodayVariable());
1465 	v_yesterday = (KnownVariable*) addVariable(new YesterdayVariable());
1466 	v_tomorrow = (KnownVariable*) addVariable(new TomorrowVariable());
1467 	v_now = (KnownVariable*) addVariable(new NowVariable());
1468 #if defined __linux__ || defined _WIN32
1469 	addVariable(new UptimeVariable());
1470 #endif
1471 
1472 }
1473 
addBuiltinFunctions()1474 void Calculator::addBuiltinFunctions() {
1475 
1476 	f_vector = addFunction(new VectorFunction());
1477 	f_sort = addFunction(new SortFunction());
1478 	f_rank = addFunction(new RankFunction());
1479 	f_limits = addFunction(new LimitsFunction());
1480 	//f_component = addFunction(new ComponentFunction());
1481 	f_dimension = addFunction(new DimensionFunction());
1482 	f_merge_vectors = addFunction(new MergeVectorsFunction());
1483 	f_matrix = addFunction(new MatrixFunction());
1484 	f_matrix_to_vector = addFunction(new MatrixToVectorFunction());
1485 	f_area = addFunction(new AreaFunction());
1486 	f_rows = addFunction(new RowsFunction());
1487 	f_columns = addFunction(new ColumnsFunction());
1488 	f_row = addFunction(new RowFunction());
1489 	f_column = addFunction(new ColumnFunction());
1490 	f_elements = addFunction(new ElementsFunction());
1491 	f_element = addFunction(new ElementFunction());
1492 	f_transpose = addFunction(new TransposeFunction());
1493 	f_identity = addFunction(new IdentityMatrixFunction());
1494 	f_determinant = addFunction(new DeterminantFunction());
1495 	f_permanent = addFunction(new PermanentFunction());
1496 	f_adjoint = addFunction(new AdjointFunction());
1497 	f_cofactor = addFunction(new CofactorFunction());
1498 	f_inverse = addFunction(new InverseFunction());
1499 	f_magnitude = addFunction(new MagnitudeFunction());
1500 	f_hadamard = addFunction(new HadamardFunction());
1501 	f_entrywise = addFunction(new EntrywiseFunction());
1502 	addFunction(new RRefFunction());
1503 	addFunction(new MatrixRankFunction());
1504 
1505 	f_factorial = addFunction(new FactorialFunction());
1506 	f_factorial2 = addFunction(new DoubleFactorialFunction());
1507 	f_multifactorial = addFunction(new MultiFactorialFunction());
1508 	f_binomial = addFunction(new BinomialFunction());
1509 
1510 	f_xor = addFunction(new XorFunction());
1511 	f_bitxor = addFunction(new BitXorFunction());
1512 	f_even = addFunction(new EvenFunction());
1513 	f_odd = addFunction(new OddFunction());
1514 	f_shift = addFunction(new ShiftFunction());
1515 	f_bitcmp = addFunction(new BitCmpFunction());
1516 	addFunction(new CircularShiftFunction());
1517 
1518 	f_abs = addFunction(new AbsFunction());
1519 	f_signum = addFunction(new SignumFunction());
1520 	f_heaviside = addFunction(new HeavisideFunction());
1521 	f_dirac = addFunction(new DiracFunction());
1522 	f_gcd = addFunction(new GcdFunction());
1523 	f_lcm = addFunction(new LcmFunction());
1524 	f_round = addFunction(new RoundFunction());
1525 	f_floor = addFunction(new FloorFunction());
1526 	f_ceil = addFunction(new CeilFunction());
1527 	f_trunc = addFunction(new TruncFunction());
1528 	f_int = addFunction(new IntFunction());
1529 	f_frac = addFunction(new FracFunction());
1530 	f_rem = addFunction(new RemFunction());
1531 	f_mod = addFunction(new ModFunction());
1532 	addFunction(new BernoulliFunction());
1533 	addFunction(new TotientFunction());
1534 
1535 	f_polynomial_unit = addFunction(new PolynomialUnitFunction());
1536 	f_polynomial_primpart = addFunction(new PolynomialPrimpartFunction());
1537 	f_polynomial_content = addFunction(new PolynomialContentFunction());
1538 	f_coeff = addFunction(new CoeffFunction());
1539 	f_lcoeff = addFunction(new LCoeffFunction());
1540 	f_tcoeff = addFunction(new TCoeffFunction());
1541 	f_degree = addFunction(new DegreeFunction());
1542 	f_ldegree = addFunction(new LDegreeFunction());
1543 
1544 	f_re = addFunction(new ReFunction());
1545 	f_im = addFunction(new ImFunction());
1546 	f_arg = addFunction(new ArgFunction());
1547 	f_numerator = addFunction(new NumeratorFunction());
1548 	f_denominator = addFunction(new DenominatorFunction());
1549 
1550 	f_interval = addFunction(new IntervalFunction());
1551 	f_uncertainty = addFunction(new UncertaintyFunction());
1552 
1553 	f_sqrt = addFunction(new SqrtFunction());
1554 	f_cbrt = addFunction(new CbrtFunction());
1555 	f_root = addFunction(new RootFunction());
1556 	f_sq = addFunction(new SquareFunction());
1557 
1558 	f_exp = addFunction(new ExpFunction());
1559 
1560 	f_ln = addFunction(new LogFunction());
1561 	f_logn = addFunction(new LognFunction());
1562 
1563 	f_lambert_w = addFunction(new LambertWFunction());
1564 
1565 	f_sin = addFunction(new SinFunction());
1566 	f_cos = addFunction(new CosFunction());
1567 	f_tan = addFunction(new TanFunction());
1568 	f_asin = addFunction(new AsinFunction());
1569 	f_acos = addFunction(new AcosFunction());
1570 	f_atan = addFunction(new AtanFunction());
1571 	f_sinh = addFunction(new SinhFunction());
1572 	f_cosh = addFunction(new CoshFunction());
1573 	f_tanh = addFunction(new TanhFunction());
1574 	f_asinh = addFunction(new AsinhFunction());
1575 	f_acosh = addFunction(new AcoshFunction());
1576 	f_atanh = addFunction(new AtanhFunction());
1577 	f_atan2 = addFunction(new Atan2Function());
1578 	f_sinc = addFunction(new SincFunction());
1579 	priv->f_cis = addFunction(new CisFunction());
1580 	f_radians_to_default_angle_unit = addFunction(new RadiansToDefaultAngleUnitFunction());
1581 
1582 	f_zeta = addFunction(new ZetaFunction());
1583 	f_gamma = addFunction(new GammaFunction());
1584 	f_digamma = addFunction(new DigammaFunction());
1585 	f_beta = addFunction(new BetaFunction());
1586 	f_airy = addFunction(new AiryFunction());
1587 	f_besselj = addFunction(new BesseljFunction());
1588 	f_bessely = addFunction(new BesselyFunction());
1589 	f_erf = addFunction(new ErfFunction());
1590 	priv->f_erfi = addFunction(new ErfiFunction());
1591 	f_erfc = addFunction(new ErfcFunction());
1592 
1593 	f_total = addFunction(new TotalFunction());
1594 	f_percentile = addFunction(new PercentileFunction());
1595 	f_min = addFunction(new MinFunction());
1596 	f_max = addFunction(new MaxFunction());
1597 	f_mode = addFunction(new ModeFunction());
1598 	f_rand = addFunction(new RandFunction());
1599 	addFunction(new RandnFunction());
1600 	addFunction(new RandPoissonFunction());
1601 
1602 	f_date = addFunction(new DateFunction());
1603 	f_datetime = addFunction(new DateTimeFunction());
1604 	f_timevalue = addFunction(new TimeValueFunction());
1605 	f_timestamp = addFunction(new TimestampFunction());
1606 	f_stamptodate = addFunction(new TimestampToDateFunction());
1607 	f_days = addFunction(new DaysFunction());
1608 	f_yearfrac = addFunction(new YearFracFunction());
1609 	f_week = addFunction(new WeekFunction());
1610 	f_weekday = addFunction(new WeekdayFunction());
1611 	f_month = addFunction(new MonthFunction());
1612 	f_day = addFunction(new DayFunction());
1613 	f_year = addFunction(new YearFunction());
1614 	f_yearday = addFunction(new YeardayFunction());
1615 	f_time = addFunction(new TimeFunction());
1616 	f_add_days = addFunction(new AddDaysFunction());
1617 	f_add_months = addFunction(new AddMonthsFunction());
1618 	f_add_years = addFunction(new AddYearsFunction());
1619 
1620 	f_lunarphase = addFunction(new LunarPhaseFunction());
1621 	f_nextlunarphase = addFunction(new NextLunarPhaseFunction());
1622 
1623 	f_base = addFunction(new BaseFunction());
1624 	f_bin = addFunction(new BinFunction());
1625 	f_oct = addFunction(new OctFunction());
1626 	addFunction(new DecFunction());
1627 	f_hex = addFunction(new HexFunction());
1628 	f_roman = addFunction(new RomanFunction());
1629 	addFunction(new BijectiveFunction());
1630 
1631 	addFunction(new IEEE754FloatFunction());
1632 	addFunction(new IEEE754FloatBitsFunction());
1633 	addFunction(new IEEE754FloatComponentsFunction());
1634 	addFunction(new IEEE754FloatValueFunction());
1635 	addFunction(new IEEE754FloatErrorFunction());
1636 
1637 	f_ascii = addFunction(new AsciiFunction());
1638 	f_char = addFunction(new CharFunction());
1639 
1640 	f_length = addFunction(new LengthFunction());
1641 	f_concatenate = addFunction(new ConcatenateFunction());
1642 
1643 	f_replace = addFunction(new ReplaceFunction());
1644 	f_stripunits = addFunction(new StripUnitsFunction());
1645 
1646 	f_genvector = addFunction(new GenerateVectorFunction());
1647 	f_for = addFunction(new ForFunction());
1648 	f_sum = addFunction(new SumFunction());
1649 	f_product = addFunction(new ProductFunction());
1650 	f_process = addFunction(new ProcessFunction());
1651 	f_process_matrix = addFunction(new ProcessMatrixFunction());
1652 	f_csum = addFunction(new CustomSumFunction());
1653 	f_function = addFunction(new FunctionFunction());
1654 	f_select = addFunction(new SelectFunction());
1655 	f_title = addFunction(new TitleFunction());
1656 	f_if = addFunction(new IFFunction());
1657 	f_is_number = addFunction(new IsNumberFunction());
1658 	f_is_real = addFunction(new IsRealFunction());
1659 	f_is_rational = addFunction(new IsRationalFunction());
1660 	f_is_integer = addFunction(new IsIntegerFunction());
1661 	f_represents_number = addFunction(new RepresentsNumberFunction());
1662 	f_represents_real = addFunction(new RepresentsRealFunction());
1663 	f_represents_rational = addFunction(new RepresentsRationalFunction());
1664 	f_represents_integer = addFunction(new RepresentsIntegerFunction());
1665 	f_error = addFunction(new ErrorFunction());
1666 	f_warning = addFunction(new WarningFunction());
1667 	f_message = addFunction(new MessageFunction());
1668 
1669 	f_save = addFunction(new SaveFunction());
1670 	f_load = addFunction(new LoadFunction());
1671 	f_export = addFunction(new ExportFunction());
1672 
1673 	f_register = addFunction(new RegisterFunction());
1674 	f_stack = addFunction(new StackFunction());
1675 
1676 	f_diff = addFunction(new DeriveFunction());
1677 	f_integrate = addFunction(new IntegrateFunction());
1678 	addFunction(new RombergFunction());
1679 	addFunction(new MonteCarloFunction());
1680 	f_solve = addFunction(new SolveFunction());
1681 	f_multisolve = addFunction(new SolveMultipleFunction());
1682 	f_dsolve = addFunction(new DSolveFunction());
1683 	f_limit = addFunction(new LimitFunction());
1684 
1685 	f_li = addFunction(new liFunction());
1686 	f_Li = addFunction(new LiFunction());
1687 	f_Ei = addFunction(new EiFunction());
1688 	f_Si = addFunction(new SiFunction());
1689 	f_Ci = addFunction(new CiFunction());
1690 	f_Shi = addFunction(new ShiFunction());
1691 	f_Chi = addFunction(new ChiFunction());
1692 	priv->f_fresnels = addFunction(new FresnelSFunction());
1693 	priv->f_fresnelc = addFunction(new FresnelCFunction());
1694 	f_igamma = addFunction(new IGammaFunction());
1695 
1696 	if(canPlot()) f_plot = addFunction(new PlotFunction());
1697 	else f_plot = NULL;
1698 
1699 	/*void *plugin = dlopen("", RTLD_NOW);
1700 	if(plugin) {
1701 		CREATEPLUG_PROC createproc = (CREATEPLUG_PROC) dlsym(plugin, "createPlugin");
1702 		if (dlerror() != NULL) {
1703 			dlclose(plugin);
1704 			printf( "dlsym error\n");
1705 		} else {
1706 			createproc();
1707 		}
1708 	} else {
1709 		printf( "dlopen error\n");
1710 	}*/
1711 
1712 }
addBuiltinUnits()1713 void Calculator::addBuiltinUnits() {
1714 	u_euro = addUnit(new Unit(_("Currency"), "EUR", "euros", "euro", "European Euros", false, true, true));
1715 	u_btc = addUnit(new AliasUnit(_("Currency"), "BTC", "bitcoins", "bitcoin", "Bitcoins", u_euro, "35450.0", 1, "", false, true, true));
1716 	u_btc->setApproximate();
1717 	u_btc->setPrecision(-2);
1718 	u_btc->setChanged(false);
1719 	priv->u_byn = addUnit(new AliasUnit(_("Currency"), "BYN", "", "", "Belarusian Ruble", u_euro, "1/3.1448", 1, "", false, true, true));
1720 	priv->u_byn->setApproximate();
1721 	priv->u_byn->setPrecision(-2);
1722 	priv->u_byn->setChanged(false);
1723 	Unit *u = addUnit(new AliasUnit(_("Currency"), "BYR", "", "", "Belarusian Ruble p. (obsolete)", priv->u_byn, "0.0001", 1, "", false, true, true));
1724 	u->setHidden(true);
1725 	u->setChanged(false);
1726 	priv->u_kelvin = NULL;
1727 	priv->u_rankine = NULL;
1728 	priv->u_celsius = NULL;
1729 	priv->u_fahrenheit = NULL;
1730 	u_second = NULL;
1731 	u_minute = NULL;
1732 	u_hour = NULL;
1733 	u_day = NULL;
1734 	u_month = NULL;
1735 	u_year = NULL;
1736 }
1737 
setVariableUnitsEnabled(bool enable_variable_units)1738 void Calculator::setVariableUnitsEnabled(bool enable_variable_units) {
1739 	b_var_units = enable_variable_units;
1740 }
variableUnitsEnabled() const1741 bool Calculator::variableUnitsEnabled() const {
1742 	return b_var_units;
1743 }
1744 
error(bool critical,int message_category,const char * TEMPLATE,...)1745 void Calculator::error(bool critical, int message_category, const char *TEMPLATE, ...) {
1746 	va_list ap;
1747 	va_start(ap, TEMPLATE);
1748 	message(critical ? MESSAGE_ERROR : MESSAGE_WARNING, message_category, TEMPLATE, ap);
1749 	va_end(ap);
1750 }
error(bool critical,const char * TEMPLATE,...)1751 void Calculator::error(bool critical, const char *TEMPLATE, ...) {
1752 	va_list ap;
1753 	va_start(ap, TEMPLATE);
1754 	message(critical ? MESSAGE_ERROR : MESSAGE_WARNING, MESSAGE_CATEGORY_NONE, TEMPLATE, ap);
1755 	va_end(ap);
1756 }
message(MessageType mtype,int message_category,const char * TEMPLATE,...)1757 void Calculator::message(MessageType mtype, int message_category, const char *TEMPLATE, ...) {
1758 	va_list ap;
1759 	va_start(ap, TEMPLATE);
1760 	message(mtype, message_category, TEMPLATE, ap);
1761 	va_end(ap);
1762 }
message(MessageType mtype,const char * TEMPLATE,...)1763 void Calculator::message(MessageType mtype, const char *TEMPLATE, ...) {
1764 	va_list ap;
1765 	va_start(ap, TEMPLATE);
1766 	message(mtype, MESSAGE_CATEGORY_NONE, TEMPLATE, ap);
1767 	va_end(ap);
1768 }
message(MessageType mtype,int message_category,const char * TEMPLATE,va_list ap)1769 void Calculator::message(MessageType mtype, int message_category, const char *TEMPLATE, va_list ap) {
1770 	if(disable_errors_ref > 0) {
1771 		stopped_messages_count[disable_errors_ref - 1]++;
1772 		if(mtype == MESSAGE_ERROR) {
1773 			stopped_errors_count[disable_errors_ref - 1]++;
1774 		} else if(mtype == MESSAGE_WARNING) {
1775 			stopped_warnings_count[disable_errors_ref - 1]++;
1776 		}
1777 	}
1778 	string error_str = TEMPLATE;
1779 	size_t i = 0;
1780 	while(true) {
1781 		i = error_str.find("%", i);
1782 		if(i == string::npos || i + 1 == error_str.length()) break;
1783 		switch(error_str[i + 1]) {
1784 			case 's': {
1785 				const char *str = va_arg(ap, const char*);
1786 				if(!str) {
1787 					i++;
1788 				} else {
1789 					error_str.replace(i, 2, str);
1790 					i += strlen(str);
1791 				}
1792 				break;
1793 			}
1794 			case 'c': {
1795 				char c = (char) va_arg(ap, int);
1796 				if(c > 0) {
1797 					error_str.replace(i, 2, 1, c);
1798 				}
1799 				i++;
1800 				break;
1801 			}
1802 			default: {
1803 				i++;
1804 				break;
1805 			}
1806 		}
1807 	}
1808 	bool dup_error = false;
1809 	for(i = 0; i < messages.size(); i++) {
1810 		if(error_str == messages[i].message()) {
1811 			dup_error = true;
1812 			break;
1813 		}
1814 	}
1815 	if(disable_errors_ref > 0) {
1816 		for(size_t i2 = 0; !dup_error && i2 < (size_t) disable_errors_ref; i2++) {
1817 			for(i = 0; i < stopped_messages[i2].size(); i++) {
1818 				if(error_str == stopped_messages[i2][i].message()) {
1819 					dup_error = true;
1820 					break;
1821 				}
1822 			}
1823 		}
1824 	}
1825 	if(!dup_error) {
1826 		if(disable_errors_ref > 0) stopped_messages[disable_errors_ref - 1].push_back(CalculatorMessage(error_str, mtype, message_category, current_stage));
1827 		else messages.push_back(CalculatorMessage(error_str, mtype, message_category, current_stage));
1828 	}
1829 }
message()1830 CalculatorMessage* Calculator::message() {
1831 	if(!messages.empty()) {
1832 		return &messages[0];
1833 	}
1834 	return NULL;
1835 }
nextMessage()1836 CalculatorMessage* Calculator::nextMessage() {
1837 	if(!messages.empty()) {
1838 		messages.erase(messages.begin());
1839 		if(!messages.empty()) {
1840 			return &messages[0];
1841 		}
1842 	}
1843 	return NULL;
1844 }
clearMessages()1845 void Calculator::clearMessages() {
1846 	messages.clear();
1847 }
cleanMessages(const MathStructure & mstruct,size_t first_message)1848 void Calculator::cleanMessages(const MathStructure &mstruct, size_t first_message) {
1849 	if(first_message > 0) first_message--;
1850 	if(messages.size() <= first_message) return;
1851 	if(mstruct.containsInterval(true, false, false, -2, true) <= 0) {
1852 		for(size_t i = messages.size() - 1; ; i--) {
1853 			if(messages[i].category() == MESSAGE_CATEGORY_WIDE_INTERVAL) {
1854 				messages.erase(messages.begin() + i);
1855 			}
1856 			if(i == first_message) break;
1857 		}
1858 	}
1859 }
deleteName(string name_,ExpressionItem * object)1860 void Calculator::deleteName(string name_, ExpressionItem *object) {
1861 	Variable *v2 = getVariable(name_);
1862 	if(v2 == object) {
1863 		return;
1864 	}
1865 	if(v2 != NULL) {
1866 		v2->destroy();
1867 	} else {
1868 		MathFunction *f2 = getFunction(name_);
1869 		if(f2 == object)
1870 			return;
1871 		if(f2 != NULL) {
1872 			f2->destroy();
1873 		}
1874 	}
1875 	deleteName(name_, object);
1876 }
deleteUnitName(string name_,Unit * object)1877 void Calculator::deleteUnitName(string name_, Unit *object) {
1878 	Unit *u2 = getUnit(name_);
1879 	if(u2) {
1880 		if(u2 != object) {
1881 			u2->destroy();
1882 		}
1883 		return;
1884 	}
1885 	u2 = getCompositeUnit(name_);
1886 	if(u2) {
1887 		if(u2 != object) {
1888 			u2->destroy();
1889 		}
1890 	}
1891 	deleteUnitName(name_, object);
1892 }
1893 
localizeExpression(string str,const ParseOptions & po) const1894 string Calculator::localizeExpression(string str, const ParseOptions &po) const {
1895 	if((DOT_STR == DOT && COMMA_STR == COMMA && !po.comma_as_separator) || po.base == BASE_UNICODE || (po.base == BASE_CUSTOM && priv->custom_input_base_i > 62)) return str;
1896 	vector<size_t> q_begin;
1897 	vector<size_t> q_end;
1898 	size_t i3 = 0;
1899 	while(true) {
1900 		i3 = str.find_first_of("\"\'", i3);
1901 		if(i3 == string::npos) {
1902 			break;
1903 		}
1904 		q_begin.push_back(i3);
1905 		i3 = str.find(str[i3], i3 + 1);
1906 		if(i3 == string::npos) {
1907 			q_end.push_back(str.length() - 1);
1908 			break;
1909 		}
1910 		q_end.push_back(i3);
1911 		i3++;
1912 	}
1913 	if(COMMA_STR != COMMA || po.comma_as_separator) {
1914 		bool b_alt_comma = po.comma_as_separator && COMMA_STR == COMMA;
1915 		size_t ui = str.find(COMMA);
1916 		while(ui != string::npos) {
1917 			bool b = false;
1918 			for(size_t ui2 = 0; ui2 < q_end.size(); ui2++) {
1919 				if(ui <= q_end[ui2] && ui >= q_begin[ui2]) {
1920 					ui = str.find(COMMA, q_end[ui2] + 1);
1921 					b = true;
1922 					break;
1923 				}
1924 			}
1925 			if(!b) {
1926 				str.replace(ui, strlen(COMMA), b_alt_comma ? ";" : COMMA_STR);
1927 				ui = str.find(COMMA, ui + (b_alt_comma ? 1 : COMMA_STR.length()));
1928 			}
1929 		}
1930 	}
1931 	if(DOT_STR != DOT) {
1932 		size_t ui = str.find(DOT);
1933 		while(ui != string::npos) {
1934 			bool b = false;
1935 			for(size_t ui2 = 0; ui2 < q_end.size(); ui2++) {
1936 				if(ui <= q_end[ui2] && ui >= q_begin[ui2]) {
1937 					ui = str.find(DOT, q_end[ui2] + 1);
1938 					b = true;
1939 					break;
1940 				}
1941 			}
1942 			if(!b) {
1943 				str.replace(ui, strlen(DOT), DOT_STR);
1944 				ui = str.find(DOT, ui + DOT_STR.length());
1945 			}
1946 		}
1947 	}
1948 	return str;
1949 }
unlocalizeExpression(string str,const ParseOptions & po) const1950 string Calculator::unlocalizeExpression(string str, const ParseOptions &po) const {
1951 	if((DOT_STR == DOT && COMMA_STR == COMMA && !po.comma_as_separator) || po.base == BASE_UNICODE || (po.base == BASE_CUSTOM && priv->custom_input_base_i > 62)) return str;
1952 	int base = po.base;
1953 	if(base == BASE_CUSTOM) {
1954 		base = (int) priv->custom_input_base_i;
1955 	} else if(base == BASE_BIJECTIVE_26) {
1956 		base = 36;
1957 	} else if(base == BASE_GOLDEN_RATIO || base == BASE_SUPER_GOLDEN_RATIO || base == BASE_SQRT2) {
1958 		base = 2;
1959 	} else if(base == BASE_PI) {
1960 		base = 4;
1961 	} else if(base == BASE_E) {
1962 		base = 3;
1963 	} else if(base == BASE_DUODECIMAL) {
1964 		base = -12;
1965 	} else if(base < 2 || base > 36) {
1966 		base = -1;
1967 	}
1968 	vector<size_t> q_begin;
1969 	vector<size_t> q_end;
1970 	size_t i3 = 0;
1971 	while(true) {
1972 		i3 = str.find_first_of("\"\'", i3);
1973 		if(i3 == string::npos) {
1974 			break;
1975 		}
1976 		q_begin.push_back(i3);
1977 		i3 = str.find(str[i3], i3 + 1);
1978 		if(i3 == string::npos) {
1979 			q_end.push_back(str.length() - 1);
1980 			break;
1981 		}
1982 		q_end.push_back(i3);
1983 		i3++;
1984 	}
1985 	if(DOT_STR != DOT) {
1986 		if(DOT_STR == COMMA && str.find(COMMA_STR) == string::npos && base > 0 && base <= 10) {
1987 			bool b_vector = (str.find(LEFT_VECTOR_WRAP) != string::npos && !po.dot_as_separator);
1988 			bool b_dot = (str.find(DOT) != string::npos);
1989 			size_t ui = str.find_first_of(b_vector ? DOT COMMA : COMMA);
1990 			size_t ui2 = 0;
1991 			while(ui != string::npos) {
1992 				for(; ui2 < q_end.size(); ui2++) {
1993 					if(ui >= q_begin[ui2]) {
1994 						if(ui <= q_end[ui2]) {
1995 							ui = str.find_first_of(b_vector ? DOT COMMA : COMMA, q_end[ui2] + 1);
1996 							if(ui == string::npos) break;
1997 						}
1998 					} else {
1999 						break;
2000 					}
2001 				}
2002 				if(ui == string::npos) break;
2003 				if(ui > 0) {
2004 					size_t ui3 = str.find_last_not_of(SPACES, ui - 1);
2005 					if(ui3 != string::npos && ((str[ui3] > 'a' && str[ui3] < 'z') || (str[ui3] > 'A' && str[ui3] < 'Z')) && is_not_number(str[ui3], base)) return str;
2006 				}
2007 				if(ui != str.length() - 1) {
2008 					size_t ui3 = str.find_first_not_of(SPACES, ui + 1);
2009 					if(ui3 != string::npos && is_not_number(str[ui3], base)) return str;
2010 					if(b_vector || !b_dot) {
2011 						ui3 = str.find_first_not_of(SPACES NUMBERS, ui3 + 1);
2012 						if(ui3 != string::npos && (str[ui3] == COMMA_CH || (b_vector && str[ui3] == DOT_CH))) return str;
2013 					}
2014 				}
2015 				ui = str.find(b_vector ? DOT COMMA : COMMA, ui + 1);
2016 			}
2017 		}
2018 		if(po.dot_as_separator) {
2019 			size_t ui = str.find(DOT);
2020 			size_t ui2 = 0;
2021 			while(ui != string::npos) {
2022 				for(; ui2 < q_end.size(); ui2++) {
2023 					if(ui >= q_begin[ui2]) {
2024 						if(ui <= q_end[ui2]) {
2025 							ui = str.find(DOT, q_end[ui2] + 1);
2026 							if(ui == string::npos) break;
2027 						}
2028 					} else {
2029 						break;
2030 					}
2031 				}
2032 				if(ui == string::npos) break;
2033 				str.replace(ui, strlen(DOT), SPACE);
2034 				ui = str.find(DOT, ui + strlen(SPACE));
2035 			}
2036 		}
2037 		size_t ui2 = 0;
2038 		size_t ui = str.find(DOT_STR);
2039 		while(ui != string::npos) {
2040 			for(; ui2 < q_end.size(); ui2++) {
2041 				if(ui >= q_begin[ui2]) {
2042 					if(ui <= q_end[ui2]) {
2043 						ui = str.find(DOT_STR, q_end[ui2] + 1);
2044 						if(ui == string::npos) break;
2045 					}
2046 				} else {
2047 					break;
2048 				}
2049 			}
2050 			if(ui == string::npos) break;
2051 			str.replace(ui, DOT_STR.length(), DOT);
2052 			ui = str.find(DOT_STR, ui + strlen(DOT));
2053 		}
2054 	}
2055 	if(COMMA_STR != COMMA || po.comma_as_separator) {
2056 		bool b_alt_comma = po.comma_as_separator && COMMA_STR == COMMA;
2057 		if(po.comma_as_separator) {
2058 			size_t ui = str.find(COMMA);
2059 			size_t ui2 = 0;
2060 			while(ui != string::npos) {
2061 				for(; ui2 < q_end.size(); ui2++) {
2062 					if(ui >= q_begin[ui2]) {
2063 						if(ui <= q_end[ui2]) {
2064 							ui = str.find(COMMA, q_end[ui2] + 1);
2065 							if(ui == string::npos) break;
2066 						}
2067 					} else {
2068 						break;
2069 					}
2070 				}
2071 				if(ui == string::npos) break;
2072 				str.erase(ui, strlen(COMMA));
2073 				ui = str.find(COMMA, ui);
2074 			}
2075 		}
2076 		size_t ui2 = 0;
2077 		size_t ui = str.find(b_alt_comma ? ";" : COMMA_STR);
2078 		while(ui != string::npos) {
2079 			for(; ui2 < q_end.size(); ui2++) {
2080 				if(ui >= q_begin[ui2]) {
2081 					if(ui <= q_end[ui2]) {
2082 						ui = str.find(b_alt_comma ? ";" : COMMA_STR, q_end[ui2] + 1);
2083 						if(ui == string::npos) break;
2084 					}
2085 				} else {
2086 					break;
2087 				}
2088 			}
2089 			if(ui == string::npos) break;
2090 			str.replace(ui, b_alt_comma ? 1 : COMMA_STR.length(), COMMA);
2091 			ui = str.find(b_alt_comma ? ";" : COMMA_STR, ui + strlen(COMMA));
2092 		}
2093 	}
2094 	return str;
2095 }
2096 
addUnit(Unit * u,bool force,bool check_names)2097 Unit* Calculator::addUnit(Unit *u, bool force, bool check_names) {
2098 	if(check_names) {
2099 		for(size_t i = 1; i <= u->countNames(); i++) {
2100 			u->setName(getName(u->getName(i).name, u, force), i);
2101 		}
2102 	}
2103 	if(!u->isLocal() && units.size() > 0 && units[units.size() - 1]->isLocal()) {
2104 		units.insert(units.begin(), u);
2105 	} else {
2106 		units.push_back(u);
2107 	}
2108 	unitNameChanged(u, true);
2109 	for(vector<Unit*>::iterator it = deleted_units.begin(); it != deleted_units.end(); ++it) {
2110 		if(*it == u) {
2111 			deleted_units.erase(it);
2112 			break;
2113 		}
2114 	}
2115 	u->setRegistered(true);
2116 	u->setChanged(false);
2117 	if(u->id() != 0) priv->id_units[u->id()] = u;
2118 	return u;
2119 }
delPrefixUFV(Prefix * object)2120 void Calculator::delPrefixUFV(Prefix *object) {
2121 	int i = 0;
2122 	for(vector<void*>::iterator it = ufvl.begin(); ; ++it) {
2123 		del_ufvl:
2124 		if(it == ufvl.end()) {
2125 			break;
2126 		}
2127 		if(*it == object) {
2128 			it = ufvl.erase(it);
2129 			ufvl_t.erase(ufvl_t.begin() + i);
2130 			ufvl_i.erase(ufvl_i.begin() + i);
2131 			if(it == ufvl.end()) break;
2132 			goto del_ufvl;
2133 		}
2134 		i++;
2135 	}
2136 	for(size_t i2 = 0; i2 < UFV_LENGTHS; i2++) {
2137 		i = 0;
2138 		for(vector<void*>::iterator it = ufv[0][i2].begin(); ; ++it) {
2139 			del_ufv:
2140 			if(it == ufv[0][i2].end()) {
2141 				break;
2142 			}
2143 			if(*it == object) {
2144 				it = ufv[0][i2].erase(it);
2145 				ufv_i[0][i2].erase(ufv_i[0][i2].begin() + i);
2146 				if(it == ufv[0][i2].end()) break;
2147 				goto del_ufv;
2148 			}
2149 			i++;
2150 		}
2151 	}
2152 }
delUFV(ExpressionItem * object)2153 void Calculator::delUFV(ExpressionItem *object) {
2154 	int i = 0;
2155 	for(vector<void*>::iterator it = ufvl.begin(); ; ++it) {
2156 		del_ufvl:
2157 		if(it == ufvl.end()) {
2158 			break;
2159 		}
2160 		if(*it == object) {
2161 			it = ufvl.erase(it);
2162 			ufvl_t.erase(ufvl_t.begin() + i);
2163 			ufvl_i.erase(ufvl_i.begin() + i);
2164 			if(it == ufvl.end()) break;
2165 			goto del_ufvl;
2166 		}
2167 		i++;
2168 	}
2169 	int i3 = 0;
2170 	switch(object->type()) {
2171 		case TYPE_FUNCTION: {i3 = 1; break;}
2172 		case TYPE_UNIT: {i3 = 2; break;}
2173 		case TYPE_VARIABLE: {i3 = 3; break;}
2174 	}
2175 	for(size_t i2 = 0; i2 < UFV_LENGTHS; i2++) {
2176 		i = 0;
2177 		for(vector<void*>::iterator it = ufv[i3][i2].begin(); ; ++it) {
2178 			del_ufv:
2179 			if(it == ufv[i3][i2].end()) {
2180 				break;
2181 			}
2182 			if(*it == object) {
2183 				it = ufv[i3][i2].erase(it);
2184 				ufv_i[i3][i2].erase(ufv_i[i3][i2].begin() + i);
2185 				if(it == ufv[i3][i2].end()) break;
2186 				goto del_ufv;
2187 			}
2188 			i++;
2189 		}
2190 	}
2191 }
getUnit(string name_)2192 Unit* Calculator::getUnit(string name_) {
2193 	if(name_.empty()) return NULL;
2194 	for(size_t i = 0; i < units.size(); i++) {
2195 		if(units[i]->subtype() != SUBTYPE_COMPOSITE_UNIT && (units[i]->hasName(name_))) {
2196 			return units[i];
2197 		}
2198 	}
2199 	return NULL;
2200 }
getUnitById(int id) const2201 Unit* Calculator::getUnitById(int id) const {
2202 	switch(id) {
2203 		case UNIT_ID_EURO: {return u_euro;}
2204 		case UNIT_ID_KELVIN: {return priv->u_kelvin;}
2205 		case UNIT_ID_RANKINE: {return priv->u_rankine;}
2206 		case UNIT_ID_CELSIUS: {return priv->u_celsius;}
2207 		case UNIT_ID_FAHRENHEIT: {return priv->u_fahrenheit;}
2208 		case UNIT_ID_BYN: {return priv->u_byn;}
2209 		case UNIT_ID_BTC: {return u_btc;}
2210 		case UNIT_ID_SECOND: {return u_second;}
2211 		case UNIT_ID_MINUTE: {return u_minute;}
2212 		case UNIT_ID_HOUR: {return u_hour;}
2213 		case UNIT_ID_DAY: {return u_day;}
2214 		case UNIT_ID_MONTH: {return u_month;}
2215 		case UNIT_ID_YEAR: {return u_year;}
2216 	}
2217 	unordered_map<int, Unit*>::iterator it = priv->id_units.find(id);
2218 	if(it == priv->id_units.end()) return NULL;
2219 	return it->second;
2220 }
getActiveUnit(string name_)2221 Unit* Calculator::getActiveUnit(string name_) {
2222 	if(name_.empty()) return NULL;
2223 	for(size_t i = 0; i < units.size(); i++) {
2224 		if(units[i]->isActive() && units[i]->subtype() != SUBTYPE_COMPOSITE_UNIT && units[i]->hasName(name_)) {
2225 			return units[i];
2226 		}
2227 	}
2228 	return NULL;
2229 }
getLocalCurrency()2230 Unit* Calculator::getLocalCurrency() {
2231 	if(priv->local_currency) return priv->local_currency;
2232 	struct lconv *lc = localeconv();
2233 	if(lc) {
2234 		string local_currency = lc->int_curr_symbol;
2235 		remove_blank_ends(local_currency);
2236 		if(!local_currency.empty()) {
2237 			if(local_currency.length() > 3) local_currency = local_currency.substr(0, 3);
2238 			return getActiveUnit(local_currency);
2239 		}
2240 	}
2241 	return NULL;
2242 }
setLocalCurrency(Unit * u)2243 void Calculator::setLocalCurrency(Unit *u) {
2244 	priv->local_currency = u;
2245 }
getCompositeUnit(string internal_name_)2246 Unit* Calculator::getCompositeUnit(string internal_name_) {
2247 	if(internal_name_.empty()) return NULL;
2248 	for(size_t i = 0; i < units.size(); i++) {
2249 		if(units[i]->subtype() == SUBTYPE_COMPOSITE_UNIT && units[i]->hasName(internal_name_)) {
2250 			return units[i];
2251 		}
2252 	}
2253 	return NULL;
2254 }
2255 
addVariable(Variable * v,bool force,bool check_names)2256 Variable* Calculator::addVariable(Variable *v, bool force, bool check_names) {
2257 	if(check_names) {
2258 		for(size_t i = 1; i <= v->countNames(); i++) {
2259 			v->setName(getName(v->getName(i).name, v, force), i);
2260 		}
2261 	}
2262 	if(!v->isLocal() && variables.size() > 0 && variables[variables.size() - 1]->isLocal()) {
2263 		variables.insert(variables.begin(), v);
2264 	} else {
2265 		variables.push_back(v);
2266 	}
2267 	variableNameChanged(v, true);
2268 	for(vector<Variable*>::iterator it = deleted_variables.begin(); it != deleted_variables.end(); ++it) {
2269 		if(*it == v) {
2270 			deleted_variables.erase(it);
2271 			break;
2272 		}
2273 	}
2274 	v->setRegistered(true);
2275 	v->setChanged(false);
2276 	if(v->id() != 0) priv->id_variables[v->id()] = v;
2277 	return v;
2278 }
expressionItemDeactivated(ExpressionItem * item)2279 void Calculator::expressionItemDeactivated(ExpressionItem *item) {
2280 	delUFV(item);
2281 }
expressionItemActivated(ExpressionItem * item)2282 void Calculator::expressionItemActivated(ExpressionItem *item) {
2283 	ExpressionItem *item2 = getActiveExpressionItem(item);
2284 	if(item2) {
2285 		item2->setActive(false);
2286 	}
2287 	nameChanged(item);
2288 }
expressionItemDeleted(ExpressionItem * item)2289 void Calculator::expressionItemDeleted(ExpressionItem *item) {
2290 	switch(item->type()) {
2291 		case TYPE_VARIABLE: {
2292 			for(vector<Variable*>::iterator it = variables.begin(); it != variables.end(); ++it) {
2293 				if(*it == item) {
2294 					variables.erase(it);
2295 					deleted_variables.push_back((Variable*) item);
2296 					break;
2297 				}
2298 			}
2299 			break;
2300 		}
2301 		case TYPE_FUNCTION: {
2302 			for(vector<MathFunction*>::iterator it = functions.begin(); it != functions.end(); ++it) {
2303 				if(*it == item) {
2304 					functions.erase(it);
2305 					deleted_functions.push_back((MathFunction*) item);
2306 					break;
2307 				}
2308 			}
2309 			if(item->subtype() == SUBTYPE_DATA_SET) {
2310 				for(vector<DataSet*>::iterator it = data_sets.begin(); it != data_sets.end(); ++it) {
2311 					if(*it == item) {
2312 						data_sets.erase(it);
2313 						break;
2314 					}
2315 				}
2316 			}
2317 			break;
2318 		}
2319 		case TYPE_UNIT: {
2320 			for(vector<Unit*>::iterator it = units.begin(); it != units.end(); ++it) {
2321 				if(*it == item) {
2322 					units.erase(it);
2323 					deleted_units.push_back((Unit*) item);
2324 					break;
2325 				}
2326 			}
2327 			break;
2328 		}
2329 	}
2330 	for(size_t i2 = 1; i2 <= item->countNames(); i2++) {
2331 		if(item->type() == TYPE_VARIABLE || item->type() == TYPE_UNIT) {
2332 			for(size_t i = 0; i < variables.size(); i++) {
2333 				if(!variables[i]->isLocal() && !variables[i]->isActive() && variables[i]->hasName(item->getName(i2).name, item->getName(i2).case_sensitive) && !getActiveExpressionItem(variables[i])) {variables[i]->setActive(true);}
2334 			}
2335 			for(size_t i = 0; i < units.size(); i++) {
2336 				if(!units[i]->isLocal() && !units[i]->isActive() && units[i]->hasName(item->getName(i2).name, item->getName(i2).case_sensitive) && !getActiveExpressionItem(units[i])) units[i]->setActive(true);
2337 			}
2338 		} else {
2339 			for(size_t i = 0; i < functions.size(); i++) {
2340 				if(!functions[i]->isLocal() && !functions[i]->isActive() && functions[i]->hasName(item->getName(i2).name, item->getName(i2).case_sensitive) && !getActiveExpressionItem(functions[i])) functions[i]->setActive(true);
2341 			}
2342 		}
2343 	}
2344 	delUFV(item);
2345 }
nameChanged(ExpressionItem * item,bool new_item)2346 void Calculator::nameChanged(ExpressionItem *item, bool new_item) {
2347 	if(!item->isActive() || item->countNames() == 0) return;
2348 	if(item->type() == TYPE_UNIT && ((Unit*) item)->subtype() == SUBTYPE_COMPOSITE_UNIT) {
2349 		return;
2350 	}
2351 	size_t l2;
2352 	if(!new_item) delUFV(item);
2353 	for(size_t i2 = 1; i2 <= item->countNames(); i2++) {
2354 		l2 = item->getName(i2).name.length();
2355 		if(l2 > UFV_LENGTHS) {
2356 			size_t i = 0, l = 0;
2357 			for(vector<void*>::iterator it = ufvl.begin(); ; ++it) {
2358 				if(it != ufvl.end()) {
2359 					if(ufvl_t[i] == 'v')
2360 						l = ((Variable*) (*it))->getName(ufvl_i[i]).name.length();
2361 					else if(ufvl_t[i] == 'f')
2362 						l = ((MathFunction*) (*it))->getName(ufvl_i[i]).name.length();
2363 					else if(ufvl_t[i] == 'u')
2364 						l = ((Unit*) (*it))->getName(ufvl_i[i]).name.length();
2365 					else if(ufvl_t[i] == 'p')
2366 						l = ((Prefix*) (*it))->shortName(false).length();
2367 					else if(ufvl_t[i] == 'P')
2368 						l = ((Prefix*) (*it))->longName(false).length();
2369 					else if(ufvl_t[i] == 'q')
2370 						l = ((Prefix*) (*it))->unicodeName(false).length();
2371 				}
2372 				if(it == ufvl.end()) {
2373 					ufvl.push_back((void*) item);
2374 					switch(item->type()) {
2375 						case TYPE_VARIABLE: {ufvl_t.push_back('v'); break;}
2376 						case TYPE_FUNCTION: {ufvl_t.push_back('f'); break;}
2377 						case TYPE_UNIT: {ufvl_t.push_back('u'); break;}
2378 					}
2379 					ufvl_i.push_back(i2);
2380 					break;
2381 				} else {
2382 					if(l < l2
2383 					|| (item->type() == TYPE_VARIABLE && l == l2 && ufvl_t[i] == 'v')
2384 					|| (item->type() == TYPE_FUNCTION && l == l2 && (ufvl_t[i] != 'p' && ufvl_t[i] != 'P' && ufvl_t[i] != 'q'))
2385 					|| (item->type() == TYPE_UNIT && l == l2 && (ufvl_t[i] != 'p' && ufvl_t[i] != 'P' && ufvl_t[i] != 'q' && ufvl_t[i] != 'f'))
2386 					) {
2387 						ufvl.insert(it, (void*) item);
2388 						switch(item->type()) {
2389 							case TYPE_VARIABLE: {ufvl_t.insert(ufvl_t.begin() + i, 'v'); break;}
2390 							case TYPE_FUNCTION: {ufvl_t.insert(ufvl_t.begin() + i, 'f'); break;}
2391 							case TYPE_UNIT: {ufvl_t.insert(ufvl_t.begin() + i, 'u'); break;}
2392 						}
2393 						ufvl_i.insert(ufvl_i.begin() + i, i2);
2394 						break;
2395 					}
2396 				}
2397 				i++;
2398 			}
2399 		} else if(l2 > 0) {
2400 			l2--;
2401 			switch(item->type()) {
2402 				case TYPE_VARIABLE: {
2403 					ufv[3][l2].push_back((void*) item);
2404 					ufv_i[3][l2].push_back(i2);
2405 					break;
2406 				}
2407 				case TYPE_FUNCTION:  {
2408 					ufv[1][l2].push_back((void*) item);
2409 					ufv_i[1][l2].push_back(i2);
2410 					break;
2411 				}
2412 				case TYPE_UNIT:  {
2413 					ufv[2][l2].push_back((void*) item);
2414 					ufv_i[2][l2].push_back(i2);
2415 					break;
2416 				}
2417 			}
2418 		}
2419 	}
2420 }
variableNameChanged(Variable * v,bool new_item)2421 void Calculator::variableNameChanged(Variable *v, bool new_item) {
2422 	nameChanged(v, new_item);
2423 }
functionNameChanged(MathFunction * f,bool new_item)2424 void Calculator::functionNameChanged(MathFunction *f, bool new_item) {
2425 	nameChanged(f, new_item);
2426 }
unitNameChanged(Unit * u,bool new_item)2427 void Calculator::unitNameChanged(Unit *u, bool new_item) {
2428 	nameChanged(u, new_item);
2429 }
2430 
getVariable(string name_)2431 Variable* Calculator::getVariable(string name_) {
2432 	if(name_.empty()) return NULL;
2433 	for(size_t i = 0; i < variables.size(); i++) {
2434 		if(variables[i]->hasName(name_)) {
2435 			return variables[i];
2436 		}
2437 	}
2438 	return NULL;
2439 }
getVariableById(int id) const2440 Variable* Calculator::getVariableById(int id) const {
2441 	switch(id) {
2442 		case VARIABLE_ID_E: {return v_e;}
2443 		case VARIABLE_ID_PI: {return v_pi;}
2444 		case VARIABLE_ID_EULER: {return v_euler;}
2445 		case VARIABLE_ID_CATALAN: {return v_catalan;}
2446 		case VARIABLE_ID_I: {return v_i;}
2447 		case VARIABLE_ID_PLUS_INFINITY: {return v_pinf;}
2448 		case VARIABLE_ID_MINUS_INFINITY: {return v_minf;}
2449 		case VARIABLE_ID_X: {return v_x;}
2450 		case VARIABLE_ID_Y: {return v_y;}
2451 		case VARIABLE_ID_Z: {return v_z;}
2452 		case VARIABLE_ID_N: {return v_n;}
2453 		case VARIABLE_ID_C: {return v_C;}
2454 		case VARIABLE_ID_UNDEFINED: {return v_undef;}
2455 	}
2456 	unordered_map<int, Variable*>::iterator it = priv->id_variables.find(id);
2457 	if(it == priv->id_variables.end()) return NULL;
2458 	return it->second;
2459 }
getActiveVariable(string name_)2460 Variable* Calculator::getActiveVariable(string name_) {
2461 	if(name_.empty()) return NULL;
2462 	for(size_t i = 0; i < variables.size(); i++) {
2463 		if(variables[i]->isActive() && variables[i]->hasName(name_)) {
2464 			return variables[i];
2465 		}
2466 	}
2467 	return NULL;
2468 }
addExpressionItem(ExpressionItem * item,bool force)2469 ExpressionItem* Calculator::addExpressionItem(ExpressionItem *item, bool force) {
2470 	switch(item->type()) {
2471 		case TYPE_VARIABLE: {
2472 			return addVariable((Variable*) item, force);
2473 		}
2474 		case TYPE_FUNCTION: {
2475 			if(item->subtype() == SUBTYPE_DATA_SET) return addDataSet((DataSet*) item, force);
2476 			else return addFunction((MathFunction*) item, force);
2477 		}
2478 		case TYPE_UNIT: {
2479 			return addUnit((Unit*) item, force);
2480 		}
2481 	}
2482 	return NULL;
2483 }
addFunction(MathFunction * f,bool force,bool check_names)2484 MathFunction* Calculator::addFunction(MathFunction *f, bool force, bool check_names) {
2485 	if(check_names) {
2486 		for(size_t i = 1; i <= f->countNames(); i++) {
2487 			f->setName(getName(f->getName(i).name, f, force), i);
2488 		}
2489 	}
2490 	if(!f->isLocal() && functions.size() > 0 && functions[functions.size() - 1]->isLocal()) {
2491 		functions.insert(functions.begin(), f);
2492 	} else {
2493 		functions.push_back(f);
2494 	}
2495 	functionNameChanged(f, true);
2496 	for(vector<MathFunction*>::iterator it = deleted_functions.begin(); it != deleted_functions.end(); ++it) {
2497 		if(*it == f) {
2498 			deleted_functions.erase(it);
2499 			break;
2500 		}
2501 	}
2502 	f->setRegistered(true);
2503 	f->setChanged(false);
2504 	if(f->id() != 0) priv->id_functions[f->id()] = f;
2505 	return f;
2506 }
addDataSet(DataSet * dc,bool force,bool check_names)2507 DataSet* Calculator::addDataSet(DataSet *dc, bool force, bool check_names) {
2508 	addFunction(dc, force, check_names);
2509 	data_sets.push_back(dc);
2510 	return dc;
2511 }
getDataSet(size_t index)2512 DataSet* Calculator::getDataSet(size_t index) {
2513 	if(index > 0 && index <= data_sets.size()) {
2514 		return data_sets[index - 1];
2515 	}
2516 	return 0;
2517 }
getDataSet(string name)2518 DataSet* Calculator::getDataSet(string name) {
2519 	if(name.empty()) return NULL;
2520 	for(size_t i = 0; i < data_sets.size(); i++) {
2521 		if(data_sets[i]->hasName(name)) {
2522 			return data_sets[i];
2523 		}
2524 	}
2525 	return NULL;
2526 }
getFunction(string name_)2527 MathFunction* Calculator::getFunction(string name_) {
2528 	if(name_.empty()) return NULL;
2529 	for(size_t i = 0; i < functions.size(); i++) {
2530 		if(functions[i]->hasName(name_)) {
2531 			return functions[i];
2532 		}
2533 	}
2534 	return NULL;
2535 }
getFunctionById(int id) const2536 MathFunction* Calculator::getFunctionById(int id) const {
2537 	switch(id) {
2538 		case FUNCTION_ID_SIN: {return f_sin;}
2539 		case FUNCTION_ID_COS: {return f_cos;}
2540 		case FUNCTION_ID_TAN: {return f_tan;}
2541 		case FUNCTION_ID_ASIN: {return f_asin;}
2542 		case FUNCTION_ID_ACOS: {return f_acos;}
2543 		case FUNCTION_ID_ATAN: {return f_atan;}
2544 		case FUNCTION_ID_SINH: {return f_sinh;}
2545 		case FUNCTION_ID_COSH: {return f_cosh;}
2546 		case FUNCTION_ID_TANH: {return f_tanh;}
2547 		case FUNCTION_ID_ASINH: {return f_asinh;}
2548 		case FUNCTION_ID_ACOSH: {return f_acosh;}
2549 		case FUNCTION_ID_ATANH: {return f_atanh;}
2550 		case FUNCTION_ID_SINC: {return f_sinc;}
2551 		case FUNCTION_ID_LOG: {return f_ln;}
2552 		case FUNCTION_ID_LOGN: {return f_logn;}
2553 		case FUNCTION_ID_SQRT: {return f_sqrt;}
2554 		case FUNCTION_ID_CBRT: {return f_cbrt;}
2555 		case FUNCTION_ID_ROOT: {return f_root;}
2556 		case FUNCTION_ID_CIS: {return priv->f_cis;}
2557 		case FUNCTION_ID_ABS: {return f_abs;}
2558 		case FUNCTION_ID_SIGNUM: {return f_signum;}
2559 		case FUNCTION_ID_POLYLOG: {return f_Li;}
2560 		case FUNCTION_ID_GAMMA: {return f_gamma;}
2561 		case FUNCTION_ID_ERF: {return f_erf;}
2562 		case FUNCTION_ID_ERFC: {return f_erfc;}
2563 		case FUNCTION_ID_ERFI: {return priv->f_erfi;}
2564 		case FUNCTION_ID_STRIP_UNITS: {return f_stripunits;}
2565 		case FUNCTION_ID_UNCERTAINTY: {return f_uncertainty;}
2566 		case FUNCTION_ID_INTERVAL: {return f_interval;}
2567 		case FUNCTION_ID_FACTORIAL: {return f_factorial;}
2568 		case FUNCTION_ID_DOUBLE_FACTORIAL: {return f_factorial2;}
2569 		case FUNCTION_ID_I_GAMMA: {return f_igamma;}
2570 		case FUNCTION_ID_SININT: {return f_Si;}
2571 		case FUNCTION_ID_COSINT: {return f_Ci;}
2572 		case FUNCTION_ID_SINHINT: {return f_Shi;}
2573 		case FUNCTION_ID_COSHINT: {return f_Chi;}
2574 		case FUNCTION_ID_LOGINT: {return f_li;}
2575 		case FUNCTION_ID_EXPINT: {return f_Ei;}
2576 		case FUNCTION_ID_FRESNEL_S: {return priv->f_fresnels;}
2577 		case FUNCTION_ID_FRESNEL_C: {return priv->f_fresnelc;}
2578 		case FUNCTION_ID_RE: {return f_re;}
2579 		case FUNCTION_ID_IM: {return f_im;}
2580 		case FUNCTION_ID_ARG: {return f_arg;}
2581 		case FUNCTION_ID_INTEGRATE: {return f_integrate;}
2582 		case FUNCTION_ID_DIFFERENTIATE: {return f_diff;}
2583 		case FUNCTION_ID_BETA: {return f_beta;}
2584 		case FUNCTION_ID_BESSELY: {return f_bessely;}
2585 		case FUNCTION_ID_BESSELJ: {return f_besselj;}
2586 		case FUNCTION_ID_HEAVISIDE: {return f_heaviside;}
2587 		case FUNCTION_ID_DIRAC: {return f_dirac;}
2588 		case FUNCTION_ID_DIGAMMA: {return f_digamma;}
2589 		case FUNCTION_ID_AIRY: {return f_airy;}
2590 		case FUNCTION_ID_ZETA: {return f_zeta;}
2591 		case FUNCTION_ID_LAMBERT_W: {return f_lambert_w;}
2592 		case FUNCTION_ID_IF: {return f_if;}
2593 		case FUNCTION_ID_SHIFT: {return f_shift;}
2594 		case FUNCTION_ID_XOR: {return f_xor;}
2595 	}
2596 	unordered_map<int, MathFunction*>::iterator it = priv->id_functions.find(id);
2597 	if(it == priv->id_functions.end()) return NULL;
2598 	return it->second;
2599 }
getActiveFunction(string name_)2600 MathFunction* Calculator::getActiveFunction(string name_) {
2601 	if(name_.empty()) return NULL;
2602 	for(size_t i = 0; i < functions.size(); i++) {
2603 		if(functions[i]->isActive() && functions[i]->hasName(name_)) {
2604 			return functions[i];
2605 		}
2606 	}
2607 	return NULL;
2608 }
variableNameIsValid(const string & name_)2609 bool Calculator::variableNameIsValid(const string &name_) {
2610 	return !name_.empty() && name_.find_first_of(ILLEGAL_IN_NAMES) == string::npos && is_not_in(NUMBERS, name_[0]);
2611 }
functionNameIsValid(const string & name_)2612 bool Calculator::functionNameIsValid(const string &name_) {
2613 	return !name_.empty() && name_.find_first_of(ILLEGAL_IN_NAMES) == string::npos && is_not_in(NUMBERS, name_[0]);
2614 }
unitNameIsValid(const string & name_)2615 bool Calculator::unitNameIsValid(const string &name_) {
2616 	return !name_.empty() && name_.find_first_of(ILLEGAL_IN_UNITNAMES) == string::npos;
2617 }
variableNameIsValid(const char * name_)2618 bool Calculator::variableNameIsValid(const char *name_) {
2619 	if(strlen(name_) == 0) return false;
2620 	if(is_in(NUMBERS, name_[0])) return false;
2621 	for(size_t i = 0; name_[i] != '\0'; i++) {
2622 		if(is_in(ILLEGAL_IN_NAMES, name_[i])) return false;
2623 	}
2624 	return true;
2625 }
functionNameIsValid(const char * name_)2626 bool Calculator::functionNameIsValid(const char *name_) {
2627 	if(strlen(name_) == 0) return false;
2628 	if(is_in(NUMBERS, name_[0])) return false;
2629 	for(size_t i = 0; name_[i] != '\0'; i++) {
2630 		if(is_in(ILLEGAL_IN_NAMES, name_[i])) return false;
2631 	}
2632 	return true;
2633 }
unitNameIsValid(const char * name_)2634 bool Calculator::unitNameIsValid(const char *name_) {
2635 	if(strlen(name_) == 0) return false;
2636 	for(size_t i = 0; name_[i] != '\0'; i++) {
2637 		if(is_in(ILLEGAL_IN_UNITNAMES, name_[i])) return false;
2638 	}
2639 	return true;
2640 }
2641 #define VERSION_BEFORE(i1, i2, i3) (version_numbers[0] < i1 || (version_numbers[0] == i1 && (version_numbers[1] < i2 || (version_numbers[1] == i2 && version_numbers[2] < i3))))
variableNameIsValid(const string & name_,int version_numbers[3],bool is_user_defs)2642 bool Calculator::variableNameIsValid(const string &name_, int version_numbers[3], bool is_user_defs) {
2643 	return variableNameIsValid(name_.c_str(), version_numbers, is_user_defs);
2644 }
functionNameIsValid(const string & name_,int version_numbers[3],bool is_user_defs)2645 bool Calculator::functionNameIsValid(const string &name_, int version_numbers[3], bool is_user_defs) {
2646 	return functionNameIsValid(name_.c_str(), version_numbers, is_user_defs);
2647 }
unitNameIsValid(const string & name_,int version_numbers[3],bool is_user_defs)2648 bool Calculator::unitNameIsValid(const string &name_, int version_numbers[3], bool is_user_defs) {
2649 	return unitNameIsValid(name_.c_str(), version_numbers, is_user_defs);
2650 }
variableNameIsValid(const char * name_,int version_numbers[3],bool is_user_defs)2651 bool Calculator::variableNameIsValid(const char *name_, int version_numbers[3], bool is_user_defs) {
2652 	if(strlen(name_) == 0) return false;
2653 	if(is_in(NUMBERS, name_[0])) return false;
2654 	bool b = false;
2655 	for(size_t i = 0; name_[i] != '\0'; i++) {
2656 		if(is_in(ILLEGAL_IN_NAMES, name_[i])) {
2657 			if(is_user_defs && VERSION_BEFORE(0, 8, 1) && name_[i] == BITWISE_NOT_CH) {
2658 				b = true;
2659 			} else {
2660 				return false;
2661 			}
2662 		}
2663 	}
2664 	if(b) {
2665 		error(true, _("\"%s\" is not allowed in names anymore. Please change the name of \"%s\", or the variable will be lost."), BITWISE_NOT, name_, NULL);
2666 	}
2667 	return true;
2668 }
functionNameIsValid(const char * name_,int version_numbers[3],bool is_user_defs)2669 bool Calculator::functionNameIsValid(const char *name_, int version_numbers[3], bool is_user_defs) {
2670 	if(strlen(name_) == 0) return false;
2671 	if(is_in(NUMBERS, name_[0])) return false;
2672 	bool b = false;
2673 	for(size_t i = 0; name_[i] != '\0'; i++) {
2674 		if(is_in(ILLEGAL_IN_NAMES, name_[i])) {
2675 			if(is_user_defs && VERSION_BEFORE(0, 8, 1) && name_[i] == BITWISE_NOT_CH) {
2676 				b = true;
2677 			} else {
2678 				return false;
2679 			}
2680 		}
2681 	}
2682 	if(b) {
2683 		error(true, _("\"%s\" is not allowed in names anymore. Please change the name \"%s\", or the function will be lost."), BITWISE_NOT, name_, NULL);
2684 	}
2685 	return true;
2686 }
unitNameIsValid(const char * name_,int version_numbers[3],bool is_user_defs)2687 bool Calculator::unitNameIsValid(const char *name_, int version_numbers[3], bool is_user_defs) {
2688 	if(strlen(name_) == 0) return false;
2689 	bool b = false;
2690 	for(size_t i = 0; name_[i] != '\0'; i++) {
2691 		if(is_in(ILLEGAL_IN_UNITNAMES, name_[i])) {
2692 			if(is_user_defs && VERSION_BEFORE(0, 8, 1) && name_[i] == BITWISE_NOT_CH) {
2693 				b = true;
2694 			} else {
2695 				return false;
2696 			}
2697 		}
2698 	}
2699 	if(b) {
2700 		error(true, _("\"%s\" is not allowed in names anymore. Please change the name \"%s\", or the unit will be lost."), BITWISE_NOT, name_, NULL);
2701 	}
2702 	return true;
2703 }
convertToValidVariableName(string name_)2704 string Calculator::convertToValidVariableName(string name_) {
2705 	if(name_.empty()) return "var_1";
2706 	size_t i = 0;
2707 	while(true) {
2708 		i = name_.find_first_of(ILLEGAL_IN_NAMES_MINUS_SPACE_STR, i);
2709 		if(i == string::npos)
2710 			break;
2711 		name_.erase(name_.begin() + i);
2712 	}
2713 	gsub(SPACE, UNDERSCORE, name_);
2714 	while(is_in(NUMBERS, name_[0])) {
2715 		name_.erase(name_.begin());
2716 	}
2717 	return name_;
2718 }
convertToValidFunctionName(string name_)2719 string Calculator::convertToValidFunctionName(string name_) {
2720 	if(name_.empty()) return "func_1";
2721 	return convertToValidVariableName(name_);
2722 }
convertToValidUnitName(string name_)2723 string Calculator::convertToValidUnitName(string name_) {
2724 	if(name_.empty()) return "new_unit";
2725 	size_t i = 0;
2726 	string stmp = ILLEGAL_IN_NAMES_MINUS_SPACE_STR + NUMBERS;
2727 	while(true) {
2728 		i = name_.find_first_of(stmp, i);
2729 		if(i == string::npos)
2730 			break;
2731 		name_.erase(name_.begin() + i);
2732 	}
2733 	gsub(SPACE, UNDERSCORE, name_);
2734 	return name_;
2735 }
nameTaken(string name,ExpressionItem * object)2736 bool Calculator::nameTaken(string name, ExpressionItem *object) {
2737 	if(name.empty()) return false;
2738 	if(object) {
2739 		switch(object->type()) {
2740 			case TYPE_VARIABLE: {}
2741 			case TYPE_UNIT: {
2742 				for(size_t index = 0; index < variables.size(); index++) {
2743 					if(variables[index]->isActive() && variables[index]->hasName(name)) {
2744 						return variables[index] != object;
2745 					}
2746 				}
2747 				for(size_t i = 0; i < units.size(); i++) {
2748 					if(units[i]->isActive() && units[i]->hasName(name)) {
2749 						return units[i] != object;
2750 					}
2751 				}
2752 				break;
2753 			}
2754 			case TYPE_FUNCTION: {
2755 				for(size_t index = 0; index < functions.size(); index++) {
2756 					if(functions[index]->isActive() && functions[index]->hasName(name)) {
2757 						return functions[index] != object;
2758 					}
2759 				}
2760 				break;
2761 			}
2762 		}
2763 	} else {
2764 		return getActiveExpressionItem(name) != NULL;
2765 	}
2766 	return false;
2767 }
variableNameTaken(string name,Variable * object)2768 bool Calculator::variableNameTaken(string name, Variable *object) {
2769 	if(name.empty()) return false;
2770 	for(size_t index = 0; index < variables.size(); index++) {
2771 		if(variables[index]->isActive() && variables[index]->hasName(name)) {
2772 			return variables[index] != object;
2773 		}
2774 	}
2775 
2776 	for(size_t i = 0; i < units.size(); i++) {
2777 		if(units[i]->isActive() && units[i]->hasName(name)) {
2778 			return true;
2779 		}
2780 	}
2781 	return false;
2782 }
unitNameTaken(string name,Unit * object)2783 bool Calculator::unitNameTaken(string name, Unit *object) {
2784 	if(name.empty()) return false;
2785 	for(size_t index = 0; index < variables.size(); index++) {
2786 		if(variables[index]->isActive() && variables[index]->hasName(name)) {
2787 			return true;
2788 		}
2789 	}
2790 
2791 	for(size_t i = 0; i < units.size(); i++) {
2792 		if(units[i]->isActive() && units[i]->hasName(name)) {
2793 			return units[i] == object;
2794 		}
2795 	}
2796 	return false;
2797 }
functionNameTaken(string name,MathFunction * object)2798 bool Calculator::functionNameTaken(string name, MathFunction *object) {
2799 	if(name.empty()) return false;
2800 	for(size_t index = 0; index < functions.size(); index++) {
2801 		if(functions[index]->isActive() && functions[index]->hasName(name)) {
2802 			return functions[index] != object;
2803 		}
2804 	}
2805 	return false;
2806 }
unitIsUsedByOtherUnits(const Unit * u) const2807 bool Calculator::unitIsUsedByOtherUnits(const Unit *u) const {
2808 	const Unit *u2;
2809 	for(size_t i = 0; i < units.size(); i++) {
2810 		if(units[i] != u) {
2811 			u2 = units[i];
2812 			while(u2->subtype() == SUBTYPE_ALIAS_UNIT) {
2813 				u2 = ((AliasUnit*) u2)->firstBaseUnit();
2814 				if(u2 == u) {
2815 					return true;
2816 				}
2817 			}
2818 		}
2819 	}
2820 	return false;
2821 }
2822 
getName(string name,ExpressionItem * object,bool force,bool always_append)2823 string Calculator::getName(string name, ExpressionItem *object, bool force, bool always_append) {
2824 	ExpressionItem *item = NULL;
2825 	if(!object) {
2826 	} else if(object->type() == TYPE_FUNCTION) {
2827 		item = getActiveFunction(name);
2828 	} else {
2829 		item = getActiveVariable(name);
2830 		if(!item) {
2831 			item = getActiveUnit(name);
2832 		}
2833 		if(!item) {
2834 			item = getCompositeUnit(name);
2835 		}
2836 	}
2837 	if(item && force && !name.empty() && item != object && object) {
2838 		if(!item->isLocal()) {
2839 			bool b = item->hasChanged();
2840 			if(object->isActive()) {
2841 				item->setActive(false);
2842 			}
2843 			if(!object->isLocal()) {
2844 				item->setChanged(b);
2845 			}
2846 		} else {
2847 			if(object->isActive()) {
2848 				item->destroy();
2849 			}
2850 		}
2851 		return name;
2852 	}
2853 	int i2 = 1;
2854 	bool changed = false;
2855 	if(name.empty()) {
2856 		name = "var";
2857 		always_append = true;
2858 		item = NULL;
2859 		changed = true;
2860 	}
2861 	string stmp = name;
2862 	if(always_append) {
2863 		stmp += NAME_NUMBER_PRE_STR;
2864 		stmp += "1";
2865 	}
2866 	if(changed || (item && item != object)) {
2867 		if(item) {
2868 			i2++;
2869 			stmp = name;
2870 			stmp += NAME_NUMBER_PRE_STR;
2871 			stmp += i2s(i2);
2872 		}
2873 		while(true) {
2874 			if(!object) {
2875 				item = getActiveFunction(stmp);
2876 				if(!item) {
2877 					item = getActiveVariable(stmp);
2878 				}
2879 				if(!item) {
2880 					item = getActiveUnit(stmp);
2881 				}
2882 				if(!item) {
2883 					item = getCompositeUnit(stmp);
2884 				}
2885 			} else if(object->type() == TYPE_FUNCTION) {
2886 				item = getActiveFunction(stmp);
2887 			} else {
2888 				item = getActiveVariable(stmp);
2889 				if(!item) {
2890 					item = getActiveUnit(stmp);
2891 				}
2892 				if(!item) {
2893 					item = getCompositeUnit(stmp);
2894 				}
2895 			}
2896 			if(item && item != object) {
2897 				i2++;
2898 				stmp = name;
2899 				stmp += NAME_NUMBER_PRE_STR;
2900 				stmp += i2s(i2);
2901 			} else {
2902 				break;
2903 			}
2904 		}
2905 	}
2906 	if(i2 > 1 && !always_append) {
2907 		error(false, _("Name \"%s\" is in use. Replacing with \"%s\"."), name.c_str(), stmp.c_str(), NULL);
2908 	}
2909 	return stmp;
2910 }
2911 
2912