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