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