3 * Copyright 2012 Samsung Electronics Co., Ltd
5 * Licensed under the Flora License, Version 1.1 (the License);
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://floralicense.org/license
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an AS IS BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
19 #include <math.h> /* For math functions, cos(), sin(), etc. */
24 #include "calc-main.h"
25 #include "calc-string.h"
26 #include "calc-expression.h"
27 #include "calculator_parser.h"
29 #define DECNUMDIGITS 34
30 #include "decnumber/decNumber.h"
32 #define CALCULATOR_MAX_FUNC_NUMBER 16 /**<maximum num of function*/
34 extern char decimal_ch;
35 static char g_stack[MAX_EXPRESSION_LENGTH];
37 static calculator_parentheses_data_t g_parentheses_data[MAX_PARENTHESES_NUM];
39 static int oper_num = 0;
41 static const function_t g_functions[CALCULATOR_MAX_FUNC_NUMBER] = {
42 {"x^y", "^", 1, '^', FUNCTION_POSTFIX, OPERATOR_TYPE_BINARY,
43 CALCULATOR_CALCULATE_PRIORITY_HIGH, FALSE},
44 {"ln", "ln", 2, 'L', FUNCTION_PREFIX, OPERATOR_TYPE_UNARY,
45 CALCULATOR_CALCULATE_PRIORITY_HIGHER, TRUE},
46 {"sqrt", "sqrt", 4, 'q', FUNCTION_PREFIX, OPERATOR_TYPE_UNARY,
47 CALCULATOR_CALCULATE_PRIORITY_HIGHER, TRUE},
48 {"10^x", "10^", 3, 'T', FUNCTION_PREFIX, OPERATOR_TYPE_UNARY,
49 CALCULATOR_CALCULATE_PRIORITY_HIGHER, FALSE},
50 {"x!", "!", 1, '!', FUNCTION_POSTFIX, OPERATOR_TYPE_UNARY,
51 CALCULATOR_CALCULATE_PRIORITY_HIGHEST, FALSE},
52 {"1/x", "/", 1, 'x', FUNCTION_POSTFIX, OPERATOR_TYPE_UNARY,
53 CALCULATOR_CALCULATE_PRIORITY_HIGHEST, FALSE},
54 {"sin", "sin", 3, 's', FUNCTION_PREFIX, OPERATOR_TYPE_UNARY,
55 CALCULATOR_CALCULATE_PRIORITY_HIGHER, TRUE},
56 {"cos", "cos", 3, 'c', FUNCTION_PREFIX, OPERATOR_TYPE_UNARY,
57 CALCULATOR_CALCULATE_PRIORITY_HIGHER, TRUE},
58 {"tan", "tan", 3, 't', FUNCTION_PREFIX, OPERATOR_TYPE_UNARY,
59 CALCULATOR_CALCULATE_PRIORITY_HIGHER, TRUE},
60 {"Pi", "p", 1, 'p', FUNCTION_CONSTANT, OPERATOR_TYPE_INVALID,
61 CALCULATOR_CALCULATE_PRIORITY_INVALID, FALSE},
62 {"e", "e", 1, 'e', FUNCTION_CONSTANT, OPERATOR_TYPE_INVALID,
63 CALCULATOR_CALCULATE_PRIORITY_INVALID, FALSE},
64 {"log", "log", 3, 'l', FUNCTION_PREFIX, OPERATOR_TYPE_UNARY,
65 CALCULATOR_CALCULATE_PRIORITY_HIGHER, TRUE},
66 {"abs", "abs", 3, 'b', FUNCTION_PREFIX, OPERATOR_TYPE_UNARY,
67 CALCULATOR_CALCULATE_PRIORITY_HIGHER, TRUE},
68 {"2^x", "2^", 2, '2', FUNCTION_PREFIX, OPERATOR_TYPE_UNARY,
69 CALCULATOR_CALCULATE_PRIORITY_HIGHER, FALSE},
70 {"xCy", "C", 1, 'C', FUNCTION_POSTFIX, OPERATOR_TYPE_BINARY,
71 CALCULATOR_CALCULATE_PRIORITY_HIGH, FALSE},
72 {"xPy", "P", 1, 'P', FUNCTION_POSTFIX, OPERATOR_TYPE_BINARY,
73 CALCULATOR_CALCULATE_PRIORITY_HIGH, FALSE},
76 #define CALCULATOR_GET_NODE_DATA(t) ((calculator_node_data_t*)(((GNode*)(t))->data))/**<to get data from GNode structure*/
89 __calculator_calculate_insert_node(GNode ** out_tree, GNode * to_insert,
92 GNode *upper_node = NULL;
94 calculator_node_data_t *node_data = NULL;
96 if ((!out_tree) || (!*out_tree) || (!to_insert)) {
100 upper_node = *out_tree;
103 while (CALCULATOR_GET_NODE_DATA(upper_node)->node_calcu_priority >
104 CALCULATOR_GET_NODE_DATA(to_insert)->node_calcu_priority) {
105 if (G_NODE_IS_ROOT(upper_node)) {
106 g_node_insert(to_insert, -1, upper_node);
107 CALCULATOR_GET_NODE_DATA(to_insert)->children_num++;
110 g_node_insert(*out_tree, -1, const_node); //value of last node's priority>= upper_node's > to_insert's
111 CALCULATOR_GET_NODE_DATA(*out_tree)->
117 upper_node = upper_node->parent;
120 if (CALCULATOR_GET_NODE_DATA(upper_node)->node_calcu_priority ==
121 CALCULATOR_GET_NODE_DATA(to_insert)->node_calcu_priority) {
122 if (CALCULATOR_GET_NODE_DATA(to_insert)->operator_type ==
123 OPERATOR_TYPE_BINARY) {
124 GNode *parent_node = NULL;
126 if (!G_NODE_IS_ROOT(upper_node)) {
127 parent_node = upper_node->parent;
128 g_node_unlink(upper_node);
129 g_node_insert(parent_node, -1, to_insert);
132 g_node_insert(to_insert, -1, upper_node);
133 CALCULATOR_GET_NODE_DATA(to_insert)->children_num++;
136 g_node_insert(*out_tree, -1, const_node);
137 CALCULATOR_GET_NODE_DATA(*out_tree)->
140 } else if (CALCULATOR_GET_NODE_DATA(to_insert)->operator_type ==
141 OPERATOR_TYPE_UNARY) {
142 GNode *tmp_node = NULL;
146 g_malloc0(sizeof(calculator_node_data_t));
147 node_data->cur_operator = 'x';
148 node_data->negative_flag = 1;
149 node_data->operator_type = OPERATOR_TYPE_BINARY;
150 node_data->node_calcu_priority =
151 CALCULATOR_CALCULATE_PRIORITY_MIDDLE;
152 tmp_node = g_node_new(node_data);
154 if (CALCULATOR_GET_NODE_DATA(to_insert)->
155 cur_operator != '!') {
156 __calculator_calculate_insert_node
157 (out_tree, tmp_node, const_node);
158 } else //(CALCULATOR_GET_NODE_DATA(to_insert)->cur_operator == '!')
160 g_node_insert(to_insert, -1,
162 CALCULATOR_GET_NODE_DATA(to_insert)->
166 g_node_insert(*out_tree, -1, to_insert);
167 CALCULATOR_GET_NODE_DATA(*out_tree)->
170 g_node_insert(upper_node, -1, to_insert); //combine from right
171 CALCULATOR_GET_NODE_DATA(upper_node)->
175 } else if (CALCULATOR_GET_NODE_DATA(upper_node)->node_calcu_priority <
176 CALCULATOR_GET_NODE_DATA(to_insert)->node_calcu_priority) {
177 if (CALCULATOR_GET_NODE_DATA(to_insert)->operator_type ==
178 OPERATOR_TYPE_BINARY) {
179 if (node != upper_node) {
181 CALCULATOR_GET_NODE_DATA(upper_node)->
184 g_node_insert(to_insert, -1, node);
185 CALCULATOR_GET_NODE_DATA(to_insert)->
190 if (CALCULATOR_GET_NODE_DATA(*out_tree)->
191 node_calcu_priority >
192 CALCULATOR_GET_NODE_DATA(to_insert)->
193 node_calcu_priority) {
194 g_node_insert(*out_tree, -1,
196 CALCULATOR_GET_NODE_DATA(*out_tree)->
199 g_node_insert(to_insert, -1,
201 CALCULATOR_GET_NODE_DATA(to_insert)->
206 g_node_insert(upper_node, -1, to_insert);
207 CALCULATOR_GET_NODE_DATA(upper_node)->children_num++;
210 else if (CALCULATOR_GET_NODE_DATA(to_insert)->operator_type == OPERATOR_TYPE_UNARY) //upper_node must be equal to node equalized to *out_tree, for no functions' prority higher than unary operator
214 if (CALCULATOR_GET_NODE_DATA(to_insert)->
215 cur_operator != '!') {
216 GNode *tmp_node = NULL;
220 (calculator_node_data_t));
221 node_data->cur_operator = 'x';
222 node_data->negative_flag = 1;
223 node_data->operator_type =
224 OPERATOR_TYPE_BINARY;
225 node_data->node_calcu_priority =
226 CALCULATOR_CALCULATE_PRIORITY_MIDDLE;
227 tmp_node = g_node_new(node_data);
229 __calculator_calculate_insert_node
230 (out_tree, tmp_node, const_node);
231 } else //(CALCULATOR_GET_NODE_DATA(to_insert)->cur_operator == '!')
233 g_node_insert(to_insert, -1,
235 CALCULATOR_GET_NODE_DATA(to_insert)->
240 g_node_insert(*out_tree, -1, to_insert);
241 CALCULATOR_GET_NODE_DATA(*out_tree)->children_num++;
246 *out_tree = to_insert;
260 __calculator_tree_destroy_traverse_func(GNode * node, gpointer data)
262 if (CALCULATOR_GET_NODE_DATA(node)) {
263 g_free(CALCULATOR_GET_NODE_DATA(node));
265 g_node_destroy(node);
277 static gboolean __calculator_tree_destroy_all(GNode ** tree)
283 root = g_node_get_root(*tree);
284 depth = g_node_max_height(root);
285 g_node_traverse(root, G_POST_ORDER, G_TRAVERSE_ALL, depth,
286 __calculator_tree_destroy_traverse_func, NULL);
302 static gboolean __calculator_check_overflow(double result, char *error_msg)
304 if ((result > CALCULATOR_MAX_RESULT_SUM2)
305 || (result < CALCULATOR_MIN_RESULT_SUM2)) {
306 strcat(error_msg, CALC_MSG_OUT_OF_RANGE);
314 * add parenthesis between function and paremeter.
321 static void __calculator_expression_add_parenthesis(char *exp, const char *func)
324 char *digit = "0123456789.";
326 while ((p = strstr(p, func)) != NULL) {
327 p = p + strlen(func);
329 int l = strspn(p, digit);
330 string_insert(exp, p - exp, "(");
331 string_insert(exp, p - exp + l + 1, ")");
339 * If sin/cos/tan function omitted parenthesis, add it
345 static void __calculator_expression_tri_func_parenthesis(char *exp)
347 __calculator_expression_add_parenthesis(exp, "sin");
348 __calculator_expression_add_parenthesis(exp, "cos");
349 __calculator_expression_add_parenthesis(exp, "tan");
354 * record every matching parentheses position
363 __calculator_calculate_formula_scan(char *string, int *end_idx, char *error_msg)
370 memset(g_parentheses_data, 0x0, sizeof(g_parentheses_data));
372 __calculator_expression_tri_func_parenthesis(string);
376 while (g_parentheses_data[i].start_pos) {
379 g_parentheses_data[i].start_pos = p;
382 while (g_parentheses_data[i].end_pos) {
385 if (g_parentheses_data[i].start_pos) {
386 g_parentheses_data[i].end_pos = p;
391 *end_idx = p - 1 - string;
405 static double __calculator_calculate_factorial(double n, char *err_msg)
408 strcat(err_msg, CALC_MSG_INVALID_FAC);
410 } else if (n >= 30) {
411 strcat(err_msg, CALC_MSG_OUT_OF_RANGE);
417 for (i = 2; i <= n; ++i) {
425 * Judge the op is a operator, if yes, give fucntion type
432 static gboolean __calculator_util_get_operator(char *op, function_t * function)
435 gboolean ret = FALSE;
436 if ((*op == decimal_ch) || (*op == '(') || (*op == ')')) {
438 } else if (isdigit(*op)) {
440 } else if ((*op == '+') || (*op == '-') || (*op == 'x') || (*op == '/')) {
441 function->category = FUNCTION_POSTFIX;
442 function->function_char = *op;
443 function->func_name = NULL;
444 function->func_string = NULL;
445 function->has_parentheses = FALSE;
446 function->op_type = OPERATOR_TYPE_BINARY;
447 if ((*op == '+') || (*op == '-')) {
448 function->priority = CALCULATOR_CALCULATE_PRIORITY_LOW;
450 function->priority = CALCULATOR_CALCULATE_PRIORITY_MIDDLE;
452 function->str_len = 1;
455 for (i = 0; i < CALCULATOR_MAX_FUNC_NUMBER; i++) {
457 (op, g_functions[i].func_string,
458 strlen(g_functions[i].func_string))) {
459 memcpy(function, &g_functions[i],
469 /* search function, if have, return TRUE and get the length of current function;else return FALSE */
470 gboolean __calculator_search_function(char *op, int* len)
473 gboolean ret = FALSE;
474 for (i = 0; i < CALCULATOR_MAX_FUNC_NUMBER; i++) {
475 if (!strncmp(op, g_functions[i].func_string, strlen(g_functions[i].func_string))) {
478 *len = strlen(g_functions[i].func_string);
491 * @return calculator_parentheses_data_t*
494 static calculator_parentheses_data_t
495 *__calculator_calculate_get_parentheses_info(gchar * pos)
497 calculator_parentheses_data_t *found = NULL;
500 while ((g_parentheses_data[i].start_pos) ||
501 (g_parentheses_data[i].end_pos)) {
502 if (g_parentheses_data[i].start_pos == pos) {
503 found = &g_parentheses_data[i];
505 } else if (g_parentheses_data[i].end_pos == pos) {
506 found = &g_parentheses_data[i];
528 __calculator_calculate_formula_parse(double *tmp_result, GNode ** out_tree,
529 char *start_pos, int end_idx,
533 char *end_pos = start_pos + end_idx;
536 gchar tmp[MAX_RESULT_LENGTH];
538 calculator_state_t calculator_state = CALCULATOR_OPERAND_INPUT;
539 calculator_node_data_t *node_data = NULL;
541 GNode *new_node = NULL;
542 GNode *last_node = NULL; //to proc parentheses
543 calculator_parentheses_data_t *p_data = NULL;
544 gint negative_sign = 1;
545 function_t function = { 0 };
547 memset(tmp, 0x00, sizeof(tmp));
549 if (start_pos > end_pos) {
550 strcat(error_msg, CALC_MSG_WRONG_FORMAT);
554 /* Scan from start to end of string */
555 for (p = start_pos; p <= end_pos;) {
556 q = p; /* Point to start of string */
557 if (q != NULL && __calculator_util_get_operator(q, &function)) //('.'::'('::')') and digits are four exceptions
560 if (oper_num > MAX_OPERATOR_NUM) {
561 strcat(error_msg, CALC_MSG_MAX_OP);
565 p = q + function.str_len; /* Shift */
566 if ((NULL == p) && (function.category != FUNCTION_CONSTANT)) {
569 if ((NULL != p) && (*p == decimal_ch)) {
571 strcat(error_msg, CALC_MSG_WRONG_FORMAT);
574 calculator_state = CALCULATOR_OPERATOR_INPUT;
575 if (i != 0) //save the before operator,create a node.such as 345sin(),save 345
579 node_data = g_malloc0(sizeof(calculator_node_data_t));
580 strcpy(node_data->tmp_result, tmp);
581 memset(tmp, 0x00, sizeof(tmp));
582 node_data->negative_flag = 1;
583 node_data->negative_flag *= negative_sign;
584 new_node = g_node_new(node_data);
587 if (!new_node) //no leaf node before, first factor's "+/-" sign allowed.
589 if (((function.op_type ==OPERATOR_TYPE_BINARY)&& (function.function_char != '-'))
591 ((function.op_type ==OPERATOR_TYPE_UNARY) && (function.category == FUNCTION_POSTFIX))) {
592 strcat(error_msg,CALC_MSG_WRONG_FORMAT);
594 } else if (function.function_char == '-') {
601 if (function.category == FUNCTION_CONSTANT) //Pi, e
603 if (new_node) //have the operator like 345,now it will 345*Pi
605 node_data = g_malloc0(sizeof(calculator_node_data_t));
606 node_data->cur_operator = 'x';
607 node_data->negative_flag = 1;
608 node_data->operator_type = OPERATOR_TYPE_BINARY;
609 node_data->node_calcu_priority = CALCULATOR_CALCULATE_PRIORITY_MIDDLE;
610 tree = g_node_new(node_data);
612 if (last_node == NULL) //first node
614 g_node_insert(tree, -1, new_node);
615 CALCULATOR_GET_NODE_DATA(tree)->children_num++;
617 if (CALCULATOR_GET_NODE_DATA(last_node)->children_num >
618 CALCULATOR_GET_NODE_DATA(last_node)->operator_type) {
619 strcat(error_msg, CALC_MSG_WRONG_FORMAT);
622 __calculator_calculate_insert_node(&last_node, tree, new_node);
627 } //Pi will like a leaf
628 node_data = g_malloc0(sizeof(calculator_node_data_t));
629 if (function.function_char == 'p') {
630 strcpy(node_data->tmp_result, PI_STR);
631 } else if (function.function_char == 'e') {
632 strcpy(node_data->tmp_result, EXPONENT_STR);
634 node_data->cur_operator = function.function_char;
635 node_data->node_calcu_priority = function.priority;
636 node_data->negative_flag = 1;
637 node_data->negative_flag *= negative_sign;
638 new_node = g_node_new(node_data);
641 } else if (function.category == FUNCTION_PREFIX) //sin()
643 if (!last_node) //first node
646 node_data = g_malloc0(sizeof(calculator_node_data_t));
647 node_data->cur_operator = 'x';
648 node_data->negative_flag = 1;
649 node_data->operator_type = OPERATOR_TYPE_BINARY;
650 node_data->node_calcu_priority = CALCULATOR_CALCULATE_PRIORITY_MIDDLE;
651 tree = g_node_new(node_data);
653 g_node_insert(tree, -1, new_node);
654 CALCULATOR_GET_NODE_DATA(tree)->children_num++;
663 node_data = g_malloc0(sizeof(calculator_node_data_t));
664 node_data->cur_operator = function.function_char;
665 node_data->node_calcu_priority = function.priority;
666 node_data->operator_type = function.op_type;
667 node_data->negative_flag = 1;
668 tree = g_node_new(node_data);
670 if (last_node == NULL) //first node
673 g_node_insert(tree, -1, new_node);
674 CALCULATOR_GET_NODE_DATA(tree)->children_num++;
677 if (CALCULATOR_GET_NODE_DATA(last_node)->children_num >
678 CALCULATOR_GET_NODE_DATA(last_node)->operator_type) {
679 strcat(error_msg, CALC_MSG_WRONG_FORMAT);
682 __calculator_calculate_insert_node(&last_node, tree, new_node);
691 strcat(error_msg, CALC_MSG_WRONG_FORMAT); //add for "6((" ,then "="
693 } //added by zhaodanni for prevent
694 else if (*q == decimal_ch) {
695 if (!isdigit(*p) || (calculator_state == CALCULATOR_OPERAND_FRACTION_INPUT)) {
697 calculator_state = CALCULATOR_OPERAND_FRACTION_INPUT;
700 } else if (*q == '(') {
701 if (__calculator_util_get_operator(p, &function)) {
702 if ((function.category == FUNCTION_POSTFIX) && ((*p != '+') && (*p != '-'))) //"(*","(/", not allowed.
704 strcat(error_msg, CALC_MSG_WRONG_FORMAT);
710 (!strcmp(CALCULATOR_GET_NODE_DATA(new_node)->tmp_result, PI_STR)
711 || !strcmp(CALCULATOR_GET_NODE_DATA(new_node)->tmp_result, EXPONENT_STR))) {
712 node_data =g_malloc0(sizeof(calculator_node_data_t));
713 node_data->cur_operator = 'x';
714 node_data->negative_flag = 1;
715 node_data->operator_type = OPERATOR_TYPE_BINARY;
716 node_data->node_calcu_priority = CALCULATOR_CALCULATE_PRIORITY_MIDDLE;
717 tree = g_node_new(node_data);
720 __calculator_calculate_insert_node(&last_node, tree, new_node);
722 g_node_insert(tree, -1, new_node);
723 CALCULATOR_GET_NODE_DATA(tree)->children_num++;
732 node_data = g_malloc0(sizeof(calculator_node_data_t));
733 strcpy(node_data->tmp_result, tmp);
734 memset(tmp, 0x00, sizeof(tmp));
735 node_data->negative_flag = 1;
736 node_data->negative_flag *= negative_sign;
738 new_node = g_node_new(node_data);
740 node_data = g_malloc0(sizeof(calculator_node_data_t));
741 node_data->cur_operator = 'x';
742 node_data->negative_flag = 1;
743 node_data->operator_type = OPERATOR_TYPE_BINARY;
744 node_data->node_calcu_priority =CALCULATOR_CALCULATE_PRIORITY_MIDDLE;
745 tree = g_node_new(node_data);
747 if (last_node == NULL) //first node
749 g_node_insert(tree, -1, new_node);
750 CALCULATOR_GET_NODE_DATA(tree)->children_num++;
752 if (CALCULATOR_GET_NODE_DATA(last_node)->children_num >
753 CALCULATOR_GET_NODE_DATA(last_node)->operator_type) {
754 strcat(error_msg, CALC_MSG_WRONG_FORMAT);
758 __calculator_calculate_insert_node(&last_node, tree, new_node);
764 p_data = __calculator_calculate_get_parentheses_info(q);
766 strcat(error_msg, CALC_MSG_WRONG_FORMAT);
770 } else if (*q == ')') {
771 if (*p == decimal_ch) //").", not allowed.
773 strcat(error_msg, CALC_MSG_WRONG_FORMAT);
777 p_data = __calculator_calculate_get_parentheses_info(q);
779 strcat(error_msg, CALC_MSG_WRONG_FORMAT);
782 if (!__calculator_calculate_formula_parse(NULL, &new_node, (p_data->start_pos + 1),
783 (p_data->end_pos - 1) - (p_data->start_pos + 1), error_msg)) {
784 if (new_node != NULL) {
785 __calculator_tree_destroy_all(&new_node);
787 LOGD("current node is null\n");
792 CALCULATOR_GET_NODE_DATA(new_node)->negative_flag *= negative_sign;
796 if ((*p == '(') || (isdigit(*p))) {
797 node_data = g_malloc0(sizeof(calculator_node_data_t));
798 node_data->cur_operator = 'x';
799 node_data->negative_flag = 1;
800 node_data->operator_type = OPERATOR_TYPE_BINARY;
801 node_data->node_calcu_priority = CALCULATOR_CALCULATE_PRIORITY_MIDDLE;
802 tree = g_node_new(node_data);
804 if (last_node == NULL) //first node
807 g_node_insert(tree, -1,
809 CALCULATOR_GET_NODE_DATA(tree)->
813 if (CALCULATOR_GET_NODE_DATA
814 (last_node)->children_num >
815 CALCULATOR_GET_NODE_DATA
816 (last_node)->operator_type) {
817 strcat(error_msg, CALC_MSG_WRONG_FORMAT);
821 __calculator_calculate_insert_node
822 (&last_node, tree, new_node);
827 } else if (isdigit(*q)) {
829 node_data = g_malloc0(sizeof(calculator_node_data_t));
830 node_data->cur_operator = 'x';
831 node_data->negative_flag = 1;
832 node_data->operator_type = OPERATOR_TYPE_BINARY;
833 node_data->node_calcu_priority = CALCULATOR_CALCULATE_PRIORITY_MIDDLE;
834 tree = g_node_new(node_data);
837 __calculator_calculate_insert_node(&last_node, tree, new_node);
839 g_node_insert(tree, -1, new_node);
840 CALCULATOR_GET_NODE_DATA(tree)->children_num++;
845 calculator_state = CALCULATOR_OPERAND_INPUT;
847 }/*for unvalid input ,such as "clipborad"*/
848 else if ((*q != '+') && (*q != '-') && (*q != 'x')
850 if (!__calculator_search_function(q, NULL)) {
851 printf("q=%s,line=%d\n", q, __LINE__);
852 strcat(error_msg, "invalid input");
858 if (i != 0) //last digit number
860 //if ((new_node) && (CALCULATOR_GET_NODE_DATA(new_node)->tmp_result == PI || CALCULATOR_GET_NODE_DATA(new_node)->tmp_result == EXPONENT))
864 (CALCULATOR_GET_NODE_DATA(new_node)->tmp_result, PI_STR)
865 || !strcmp(CALCULATOR_GET_NODE_DATA(new_node)->tmp_result,
867 node_data = g_malloc0(sizeof(calculator_node_data_t));
868 node_data->cur_operator = 'x';
869 node_data->negative_flag = 1;
870 node_data->operator_type = OPERATOR_TYPE_BINARY;
871 node_data->node_calcu_priority = CALCULATOR_CALCULATE_PRIORITY_MIDDLE;
872 tree = g_node_new(node_data);
875 __calculator_calculate_insert_node(&last_node, tree, new_node);
877 g_node_insert(tree, -1, new_node);
878 CALCULATOR_GET_NODE_DATA(tree)->children_num++;
885 node_data = g_malloc0(sizeof(calculator_node_data_t));
886 strcpy(node_data->tmp_result, tmp);
887 memset(tmp, 0x00, sizeof(tmp));
888 node_data->negative_flag = 1;
889 node_data->negative_flag *= negative_sign;
891 new_node = g_node_new(node_data);
893 if (last_node != NULL) {
894 if (CALCULATOR_GET_NODE_DATA(last_node)->children_num >
895 CALCULATOR_GET_NODE_DATA(last_node)->operator_type) {
896 strcat(error_msg, CALC_MSG_WRONG_FORMAT);
899 g_node_insert(last_node, -1, new_node);
900 CALCULATOR_GET_NODE_DATA(last_node)->
907 if (new_node != NULL) {
908 CALCULATOR_GET_NODE_DATA(new_node)->negative_flag *=
912 if (last_node != NULL) {
913 if (CALCULATOR_GET_NODE_DATA(last_node)->children_num >
914 CALCULATOR_GET_NODE_DATA(last_node)->operator_type) {
915 strcat(error_msg, CALC_MSG_WRONG_FORMAT);
918 g_node_insert(last_node, -1, new_node);
919 CALCULATOR_GET_NODE_DATA(last_node)->
923 last_node = new_node;
927 *out_tree = g_node_get_root(last_node);
942 __calculator_calculate_exec_traverse_func(GNode * node, gpointer data)
944 gdouble operand0, operand1 = 0.0;
945 double tmp_ret = 0.0;
946 decNumber doperand0, doperand1, dresult;
948 char dec_result[DECNUMDIGITS + 14];
949 char dec_result_tmp[MAX_RESULT_LENGTH] = { 0 };
950 char *error_msg = (char *)data;
951 char op0buf[MAX_RESULT_LENGTH] = { 0 };
952 char op1buf[MAX_RESULT_LENGTH] = { 0 };
953 if (CALCULATOR_GET_NODE_DATA(node)->children_num !=
954 CALCULATOR_GET_NODE_DATA(node)->operator_type) {
955 strcat(error_msg, CALC_MSG_NUM_AFTER_OP);
956 return TRUE; //break the recursion
959 decContextTestEndian(0);
960 decContextDefault(&set, DEC_INIT_BASE);
961 set.digits = DECNUMDIGITS;
963 if (CALCULATOR_GET_NODE_DATA(node->children)->negative_flag == -1) {
965 CALCULATOR_GET_NODE_DATA(node->children)->negative_flag = 1;
967 strcat(op0buf, CALCULATOR_GET_NODE_DATA(node->children)->tmp_result);
968 operand0 = atof(op0buf);
969 decNumberFromString(&doperand0, op0buf, &set);
971 if (CALCULATOR_GET_NODE_DATA(node)->operator_type == OPERATOR_TYPE_BINARY) {
972 if (CALCULATOR_GET_NODE_DATA
973 (node->children->next)->negative_flag == -1) {
975 CALCULATOR_GET_NODE_DATA(node->children->next)->negative_flag = 1;
977 strcat(op1buf, CALCULATOR_GET_NODE_DATA(node->children->next)->tmp_result);
978 operand1 = atof(op1buf);
979 decNumberFromString(&doperand1, op1buf, &set);
981 switch (CALCULATOR_GET_NODE_DATA(node)->cur_operator) {
983 decNumberAdd(&dresult, &doperand0, &doperand1, &set);
984 decNumberToString(&dresult, dec_result);
985 strcpy(CALCULATOR_GET_NODE_DATA(node)->tmp_result, dec_result);
988 decNumberSubtract(&dresult, &doperand0, &doperand1, &set);
989 decNumberToString(&dresult, dec_result);
990 strcpy(CALCULATOR_GET_NODE_DATA(node)->tmp_result, dec_result);
993 decNumberMultiply(&dresult, &doperand0, &doperand1, &set);
994 decNumberToString(&dresult, dec_result);
995 strcpy(CALCULATOR_GET_NODE_DATA(node)->tmp_result, dec_result);
998 if (FLOAT_EQUAL(operand1, 0)) {
999 strcat(error_msg, CALC_MSG_DIVIDE_BY_ZERO);
1000 return TRUE; //break the recursion
1002 decNumberDivide(&dresult, &doperand0, &doperand1, &set);
1003 decNumberToString(&dresult, dec_result);
1004 strcpy(CALCULATOR_GET_NODE_DATA(node)->tmp_result, dec_result);
1009 gdouble power = 0.0;
1010 power = floor(operand1);
1011 if (!FLOAT_EQUAL(power, operand1)) //operand1 is not an integer
1016 tmp_ret =pow(operand0, operand1);
1017 if (fabs(tmp_ret - 0) < 0.000001) {
1018 snprintf(dec_result_tmp, sizeof(dec_result_tmp), "%.99f", tmp_ret);
1020 snprintf(dec_result_tmp, sizeof(dec_result_tmp), "%lf", tmp_ret);
1022 strcpy(CALCULATOR_GET_NODE_DATA(node)->tmp_result, dec_result_tmp);
1023 if (!__calculator_check_overflow(atof(CALCULATOR_GET_NODE_DATA(node)->tmp_result), error_msg)) {
1029 gdouble power = 0.0;
1030 power = floor(operand1);
1031 if (!FLOAT_EQUAL(power, operand1)) //operand1 is not an integer
1033 strcat(error_msg, CALC_MSG_INVALID_FAC);
1037 if (strlen(error_msg) != 0) {
1040 tmp_ret = __calculator_calculate_factorial(operand0, error_msg);
1041 snprintf(dec_result, sizeof(dec_result), "%lf", tmp_ret);
1042 strcpy(CALCULATOR_GET_NODE_DATA(node)->tmp_result, dec_result);
1043 if (strlen(error_msg) != 0) {
1051 } else if (FLOAT_EQUAL(operand0, 0)) {
1056 decNumberLn(&dresult, &doperand0, &set);
1057 decNumberToString(&dresult, dec_result);
1058 strcpy(CALCULATOR_GET_NODE_DATA(node)->tmp_result, dec_result);
1059 if (!__calculator_check_overflow
1060 (atof(CALCULATOR_GET_NODE_DATA(node)->tmp_result),
1067 strcat(error_msg, CALC_MSG_INVALID_SQUARE);
1070 decNumberSquareRoot(&dresult, &doperand0, &set);
1071 decNumberToString(&dresult, dec_result);
1072 strcpy(CALCULATOR_GET_NODE_DATA(node)->tmp_result, dec_result);
1074 if (!__calculator_check_overflow
1075 (atof(CALCULATOR_GET_NODE_DATA(node)->tmp_result),
1081 tmp_ret = sin(operand0 * RADIAN_FACTOR);
1082 snprintf(dec_result, sizeof(dec_result), "%lf", tmp_ret);
1083 strcpy(CALCULATOR_GET_NODE_DATA(node)->tmp_result, dec_result);
1084 if (!__calculator_check_overflow
1085 (atof(CALCULATOR_GET_NODE_DATA(node)->tmp_result),
1091 tmp_ret = cos(operand0 * RADIAN_FACTOR);
1092 snprintf(dec_result, sizeof(dec_result), "%lf", tmp_ret);
1093 strcpy(CALCULATOR_GET_NODE_DATA(node)->tmp_result, dec_result);
1095 if (!__calculator_check_overflow
1096 (atof(CALCULATOR_GET_NODE_DATA(node)->tmp_result),
1102 if (FLOAT_EQUAL(fmod(operand0, 180), 90) || FLOAT_EQUAL(fmod(operand0, 180), -90)) //revise by bfl
1106 tmp_ret = tan(operand0 * RADIAN_FACTOR);
1107 snprintf(dec_result, sizeof(dec_result), "%lf", tmp_ret);
1108 strcpy(CALCULATOR_GET_NODE_DATA(node)->tmp_result, dec_result);
1109 if (!__calculator_check_overflow
1110 (atof(CALCULATOR_GET_NODE_DATA(node)->tmp_result),
1117 strcat(error_msg, CALC_MSG_INVALID_LOG);
1119 } else if (FLOAT_EQUAL(operand0, 0)) {
1120 strcat(error_msg, CALC_MSG_INVALID_LOG);
1125 decNumberLog10(&dresult, &doperand0, &set);
1126 decNumberToString(&dresult, dec_result);
1127 strcpy(CALCULATOR_GET_NODE_DATA(node)->tmp_result, dec_result);
1128 if (!__calculator_check_overflow
1129 (atof(CALCULATOR_GET_NODE_DATA(node)->tmp_result),
1135 tmp_ret = fabs(operand0);
1136 snprintf(dec_result, sizeof(dec_result), "%lf", tmp_ret);
1137 strcpy(CALCULATOR_GET_NODE_DATA(node)->tmp_result, dec_result);
1138 if (!__calculator_check_overflow
1139 (atof(CALCULATOR_GET_NODE_DATA(node)->tmp_result),
1146 decNumberFromString(&doperand1, "2", &set);
1147 decNumberPower(&dresult, &doperand1, &doperand0, &set);
1148 decNumberToString(&dresult, dec_result);
1149 strcpy(CALCULATOR_GET_NODE_DATA(node)->tmp_result, dec_result);
1150 if (!__calculator_check_overflow
1151 (atof(CALCULATOR_GET_NODE_DATA(node)->tmp_result),
1160 /*CALCULATOR_GET_NODE_DATA(node)->tmp_result *=
1161 CALCULATOR_GET_NODE_DATA(node)->negative_flag;
1162 CALCULATOR_GET_NODE_DATA(node)->negative_flag = 1;*/
1178 __calculator_calculate_exec(GNode * tree, double **result, char *error_msg)
1181 depth = g_node_max_height(tree);
1184 strcat(error_msg, CALC_MSG_WRONG_FORMAT);
1185 return FALSE; //break the recursion
1186 } else if (depth == 1) {
1187 **result = atof(CALCULATOR_GET_NODE_DATA(tree)->tmp_result);
1188 **result *= CALCULATOR_GET_NODE_DATA(tree)->negative_flag;
1191 g_node_traverse(tree,
1193 G_TRAVERSE_NON_LEAFS,
1195 __calculator_calculate_exec_traverse_func,
1196 (gpointer) error_msg);
1198 if (strlen(error_msg) > 0) {
1201 **result = atof(CALCULATOR_GET_NODE_DATA(tree)->tmp_result);
1218 bool calculator_calculate_truncate_result(double* tmp_result)
1230 * @param szInputString
1234 int calculator_get_open_braket(const char *szInputString)
1236 int nReversIndex = strlen(szInputString) - 1;
1240 while (nReversIndex >= 0) {
1241 if (szInputString[nReversIndex] == '(') {
1243 } else if (szInputString[nReversIndex] == ')') {
1248 return (nOpenCnt - nCloseCnt);
1256 * @param [out]pDigitCnt : count of digit before point(.)
1257 * @param [out]pPointCnt: count of digit after point(.)
1261 bool calculator_get_digits_number(char *szInput, int *pDigitCnt, int *pPointCnt)
1263 int nLen = strlen(szInput);
1273 for (nIndex = nLen - 1; nIndex >= 0; nIndex--) {
1274 if (isdigit(szInput[nIndex])) {
1276 } else if (szInput[nIndex] == decimal_ch) {
1277 *pPointCnt = nTempCnt;
1282 for (nIndex = 0; nIndex < nLen; nIndex++) {
1283 if (isdigit(szInput[nIndex])) {
1285 } else if (szInput[nIndex] == decimal_ch) {
1286 *pDigitCnt = nTempCntb;
1290 //*pDigitCnt = nTempCntb;
1304 bool calculator_expression_length_check(char *str, char *error_msg)
1306 int is_digit = 0, has_dot = 0;
1307 int idx = 0, nCount = 0, nDigitCnt = 0, nPointCnt = 0;
1314 if(strlen(str) > CALCULATOR_MAX_INPUT_DIGIT_NUMBER_POR)
1316 strcat(error_msg, CALC_MSG_MAX_INPUT);
1323 while (idx < strlen(str)) {
1327 if (is_digit == 0) {
1334 if (nCount > MAX_NUM_LENGTH) {
1335 strcat(error_msg, CALC_MSG_MAX_DIGIT);
1346 if(nPointCnt > CALCULATORUI_MAX_INPUT_DECIMALS)
1348 strcat(error_msg, CALC_MSG_MAX_DEC_DIGIT);
1357 else if (c == decimal_ch) {
1364 if (is_digit == 1) {
1390 bool calculator_calculate(gchar * string, gdouble * result, char *error_msg)
1393 string_replace(string, "E+", "x10^");
1394 string_replace(string, "E-", "x0.1^");
1399 memset(error_msg, 0, MAX_ERROR_MESSAGE_LENGTH);
1400 memset(g_stack, 0, sizeof(g_stack));
1403 strncpy(g_stack, string, MAX_EXPRESSION_LENGTH - 1);
1404 g_stack[MAX_EXPRESSION_LENGTH - 1] = '\0';
1406 char *digit = "0123456789pe";
1407 if (strcspn(g_stack, digit) == strlen(g_stack)) { /* no digit in expression */
1408 strcat(error_msg, CALC_MSG_WRONG_FORMAT);
1412 if (!calculator_expression_length_check(g_stack, error_msg)) {
1415 if (!__calculator_calculate_formula_scan(g_stack, &end_idx, error_msg)) {
1419 if (!__calculator_calculate_formula_parse
1420 (result, &tree, g_stack, end_idx, error_msg)) {
1422 __calculator_tree_destroy_all(&tree);
1424 LOGD("current tree is null\n");
1428 if (!__calculator_calculate_exec(tree, &result, error_msg)) {
1430 __calculator_tree_destroy_all(&tree);
1434 if (!__calculator_check_overflow(*result, error_msg)) {
1436 __calculator_tree_destroy_all(&tree);
1442 __calculator_tree_destroy_all(&tree);