1 /* This is a small demo of the high-performance GUIX graphics framework. */
2 
3 #include <stdio.h>
4 #include "gx_api.h"
5 
6 #define  PRECISSION 10
7 
8 void dtoa(double ans);
9 GX_CHAR result[128];
10 extern GX_BOOL is_decimal_point;
11 UINT string_length_get(GX_CONST GX_CHAR* input_string, UINT max_string_length);
12 VOID safe_string_copy(GX_CHAR *put, GX_CHAR *get, INT max_len);
13 
14 /* Define the struct of stack to hold operand. */
15 typedef struct STACK_OPERAND_STRUCT{
16     double operand[128];
17     int top;
18 }STACK_OPERAND;
19 
20 /* Define the struct of stack to hold operator. */
21 typedef struct STACK_OPERATION_STRUCT{
22     char operation[128];
23     int top;
24 }STACK_OPERATION;
25 
26 /* Pop an operand from operand stack. */
popOperand(STACK_OPERAND * stack,double * operand)27 UINT popOperand(STACK_OPERAND *stack, double *operand)
28 {
29 GX_VALUE top;
30 
31     top = stack -> top;
32     if(top >= 0)
33     {
34         *operand = stack -> operand[top];
35         stack -> top --;
36         return 0;
37     }
38     return 1;
39 }
40 
41 /* Push an operand to operand stack. */
pushOperand(STACK_OPERAND * stack,double operand)42 UINT pushOperand(STACK_OPERAND *stack, double operand)
43 {
44     stack -> top ++;
45     stack -> operand[stack -> top] = operand;
46     return 0;
47 }
48 
49 /* Pop an operator from operation stack. */
popOperation(STACK_OPERATION * stack,char * operation)50 UINT popOperation(STACK_OPERATION *stack, char *operation)
51 {
52 GX_VALUE top;
53 
54     top = stack -> top;
55     if (top >= 0)
56     {
57         *operation = stack -> operation[top];
58         stack -> top --;
59         return 0;
60     }
61     return 1;
62 }
63 
64 /* Push an operator to operation stack. */
pushOperation(STACK_OPERATION * stack,char operation)65 UINT pushOperation(STACK_OPERATION *stack, char operation)
66 {
67     stack -> top ++;
68     stack -> operation[stack -> top] = operation;
69     return 0;
70 }
71 
calculate(double a,char operation,double b)72 double calculate(double a, char operation, double b)
73 {
74     switch(operation)
75     {
76     case '+':
77         return a + b;
78 
79     case '-':
80         return a - b;
81 
82     case '*':
83         return a * b;
84 
85     case '/':
86         return a / b;
87     }
88     return 0;
89 }
90 
91 /* Judge whether the priority of operation1 is larger or equal to operation2. */
prior_compare(char operation1,char operation2)92 UINT prior_compare(char operation1, char operation2)
93 {
94     if ((operation1 == '*') ||(operation1 == '/'))
95     {
96         return 1;
97     }
98     else if ((operation2 == '+') ||(operation2 == '-'))
99     {
100         return 1;
101     }
102     return 0;
103 }
104 
105 /* Evaluate the arithmetic expression. */
evaluate(GX_STRING * expression,GX_BOOL persent_flag)106 void evaluate(GX_STRING *expression, GX_BOOL persent_flag)
107 {
108 STACK_OPERAND   stack_operand;
109 STACK_OPERATION stack_operation;
110 
111 GX_VALUE len = (GX_VALUE) expression -> gx_string_length;
112 GX_CONST GX_CHAR *text = expression ->gx_string_ptr;
113 double   num, ans, a, b;
114 GX_CHAR  operation;
115 GX_BOOL  is_decimal;
116 GX_VALUE decimal_len;
117 GX_CHAR  ch;
118 GX_VALUE index = 0;
119 
120     /* Initialize stack. */
121     stack_operand.top = -1;
122     stack_operation.top = -1;
123 
124     while(index < len)
125     {
126         /* Read operand to stack operand. */
127         ch = text[index];
128 
129         if ((ch >= '0') && (ch <= '9'))
130         {
131             num = 0;
132             decimal_len = 0;
133             is_decimal = GX_FALSE;
134 
135             while (((ch >= '0') && (ch <= '9')) || ch == '.')
136             {
137                 if (is_decimal)
138                 {
139                     decimal_len ++;
140                 }
141 
142                 if (ch == '.')
143                 {
144                     is_decimal = GX_TRUE;
145                 }
146                 else
147                 {
148                     num = num * 10 + ch - '0';
149                 }
150 
151                 index ++;
152                 ch = text[index];
153             }
154 
155             if (is_decimal)
156             {
157                 while (decimal_len --)
158                 {
159                     num /= 10;
160                 }
161             }
162 
163             pushOperand(&stack_operand, num);
164         }
165         else
166         {
167             /* Push current operation to stack_operation when it's priority higher than the stack top operation. */
168            if ((stack_operation.top == -1) || !prior_compare(stack_operation.operation[stack_operation.top], ch))
169            {
170                pushOperation(&stack_operation, ch);
171            }
172            else
173            {
174                /* Pop out two operands and one operation and push the calculate result to stack_operand,
175                   then push the current operation to the stack_operation. */
176                if (stack_operand.top < 1)
177                {
178                    safe_string_copy(result, "Error Format", 100);
179                    return;
180                }
181 
182                popOperand(&stack_operand, &b);
183                popOperand(&stack_operand, &a);
184                popOperation(&stack_operation, &operation);
185                ans = calculate(a, operation, b);
186 
187                pushOperand(&stack_operand, ans);
188                pushOperation(&stack_operation, ch);
189            }
190            index ++;
191         }
192     }
193 
194     while (stack_operation.top >= 0)
195     {
196         if (stack_operand.top < 1)
197         {
198             safe_string_copy(result, "Error Format", 100);
199             return;
200         }
201         popOperand(&stack_operand, &b);
202         popOperand(&stack_operand, &a);
203         popOperation(&stack_operation, &operation);
204         ans = calculate(a, operation, b);
205 
206         pushOperand(&stack_operand, ans);
207     }
208 
209     /* Pop out evaluate result. */
210     popOperand(&stack_operand, &ans);
211 
212     if (persent_flag)
213     {
214         ans /= 100;
215     }
216 
217     /* Round to the 10th decimal. */
218     if(ans >= 0)
219     {
220         ans += 0.00000000005;
221     }
222     else
223     {
224         ans += -0.00000000005;
225     }
226 
227     /* Save the calculation result to a char array. */
228     dtoa(ans);
229 }
230 
sw_pow(double a,int b)231 double sw_pow(double a, int b)
232 {
233 double result = 1;
234 
235     while (b--)
236     {
237         result *= a;
238     }
239     return result;
240 }
241 
242 /* Convert a double value to an ASCII string. */
dtoa(double ans)243 void dtoa(double ans)
244 {
245 INT digit_num = 1;
246 INT integer;
247 INT decimal[PRECISSION];
248 INT index = 0;
249 INT precision = PRECISSION;
250 double temp;
251 int result_index = 0;
252 int exponent = 0;
253 GX_BOOL exp = GX_FALSE;
254 
255     if (ans < 0)
256     {
257         result[result_index++] = '-';
258         ans *= -1;
259     }
260     if (ans >= 10000000000000000.)
261     {
262         exp = GX_TRUE;
263     }
264 
265     if(!exp)
266     {
267         /* Get integer number. */
268         temp = ans;
269         while(temp >= 10)
270         {
271             temp /= 10;
272             digit_num ++;
273         }
274 
275         /* Save the integer part to 'result' array. */
276         if(digit_num > 1)
277         {
278             temp = sw_pow(10, digit_num - 1);
279             for (index = 0; index < digit_num; index++)
280             {
281                 integer = (INT)(ans / temp);
282                 result[result_index ++] = integer + '0';
283                 ans -= integer * temp;
284                 temp /= 10;
285             }
286         }
287         else
288         {
289             integer = (INT)ans;
290             result[result_index ++] = integer + '0';
291             ans -= integer;
292         }
293     }
294     else
295     {
296 
297         while (ans >= 10)
298         {
299             ans /= 10;
300             exponent ++;
301         }
302 
303         result[result_index ++] = (INT)ans + '0';
304         ans -= (INT)ans;
305     }
306 
307     /* Save the decimal to 'decimal' array. */
308     for (index = 0; index < precision; index ++)
309     {
310         decimal[index] = (INT)(ans * 10);
311         ans = ans * 10 - decimal[index];
312     }
313 
314     for (index = precision - 1; index >= 0; index --)
315     {
316         if (decimal[index] == 0)
317         {
318             precision --;
319         }
320         else
321         {
322             break;
323         }
324     }
325 
326     if (precision)
327     {
328         result[result_index ++] = '.';
329         is_decimal_point = GX_TRUE;
330     }
331     else
332     {
333         is_decimal_point = GX_FALSE;
334     }
335 
336     /* Save the decimal to 'result' array. */
337     for(index = 0; index < precision; index ++)
338     {
339         result[result_index++] = decimal[index] + '0';
340     }
341 
342     if (!exp)
343     {
344         result[result_index] = '\0';
345     }
346     else
347     {
348         result[result_index ++] = 'E';
349         result[result_index ++] = '+';
350         gx_utility_ltoa(exponent, result + result_index, 3);
351     }
352 }
353