mirror of
https://github.com/azure-rtos/guix.git
synced 2025-01-28 07:03:11 +08:00
353 lines
7.6 KiB
C
353 lines
7.6 KiB
C
/* This is a small demo of the high-performance GUIX graphics framework. */
|
|
|
|
#include <stdio.h>
|
|
#include "gx_api.h"
|
|
|
|
#define PRECISSION 10
|
|
|
|
void dtoa(double ans);
|
|
GX_CHAR result[128];
|
|
extern GX_BOOL is_decimal_point;
|
|
UINT string_length_get(GX_CONST GX_CHAR* input_string, UINT max_string_length);
|
|
VOID safe_string_copy(GX_CHAR *put, GX_CHAR *get, INT max_len);
|
|
|
|
/* Define the struct of stack to hold operand. */
|
|
typedef struct STACK_OPERAND_STRUCT{
|
|
double operand[128];
|
|
int top;
|
|
}STACK_OPERAND;
|
|
|
|
/* Define the struct of stack to hold operator. */
|
|
typedef struct STACK_OPERATION_STRUCT{
|
|
char operation[128];
|
|
int top;
|
|
}STACK_OPERATION;
|
|
|
|
/* Pop an operand from operand stack. */
|
|
UINT popOperand(STACK_OPERAND *stack, double *operand)
|
|
{
|
|
GX_VALUE top;
|
|
|
|
top = stack -> top;
|
|
if(top >= 0)
|
|
{
|
|
*operand = stack -> operand[top];
|
|
stack -> top --;
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/* Push an operand to operand stack. */
|
|
UINT pushOperand(STACK_OPERAND *stack, double operand)
|
|
{
|
|
stack -> top ++;
|
|
stack -> operand[stack -> top] = operand;
|
|
return 0;
|
|
}
|
|
|
|
/* Pop an operator from operation stack. */
|
|
UINT popOperation(STACK_OPERATION *stack, char *operation)
|
|
{
|
|
GX_VALUE top;
|
|
|
|
top = stack -> top;
|
|
if (top >= 0)
|
|
{
|
|
*operation = stack -> operation[top];
|
|
stack -> top --;
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/* Push an operator to operation stack. */
|
|
UINT pushOperation(STACK_OPERATION *stack, char operation)
|
|
{
|
|
stack -> top ++;
|
|
stack -> operation[stack -> top] = operation;
|
|
return 0;
|
|
}
|
|
|
|
double calculate(double a, char operation, double b)
|
|
{
|
|
switch(operation)
|
|
{
|
|
case '+':
|
|
return a + b;
|
|
|
|
case '-':
|
|
return a - b;
|
|
|
|
case '*':
|
|
return a * b;
|
|
|
|
case '/':
|
|
return a / b;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* Judge whether the priority of operation1 is larger or equal to operation2. */
|
|
UINT prior_compare(char operation1, char operation2)
|
|
{
|
|
if ((operation1 == '*') ||(operation1 == '/'))
|
|
{
|
|
return 1;
|
|
}
|
|
else if ((operation2 == '+') ||(operation2 == '-'))
|
|
{
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* Evaluate the arithmetic expression. */
|
|
void evaluate(GX_STRING *expression, GX_BOOL persent_flag)
|
|
{
|
|
STACK_OPERAND stack_operand;
|
|
STACK_OPERATION stack_operation;
|
|
|
|
GX_VALUE len = (GX_VALUE) expression -> gx_string_length;
|
|
GX_CONST GX_CHAR *text = expression ->gx_string_ptr;
|
|
double num, ans, a, b;
|
|
GX_CHAR operation;
|
|
GX_BOOL is_decimal;
|
|
GX_VALUE decimal_len;
|
|
GX_CHAR ch;
|
|
GX_VALUE index = 0;
|
|
|
|
/* Initialize stack. */
|
|
stack_operand.top = -1;
|
|
stack_operation.top = -1;
|
|
|
|
while(index < len)
|
|
{
|
|
/* Read operand to stack operand. */
|
|
ch = text[index];
|
|
|
|
if ((ch >= '0') && (ch <= '9'))
|
|
{
|
|
num = 0;
|
|
decimal_len = 0;
|
|
is_decimal = GX_FALSE;
|
|
|
|
while (((ch >= '0') && (ch <= '9')) || ch == '.')
|
|
{
|
|
if (is_decimal)
|
|
{
|
|
decimal_len ++;
|
|
}
|
|
|
|
if (ch == '.')
|
|
{
|
|
is_decimal = GX_TRUE;
|
|
}
|
|
else
|
|
{
|
|
num = num * 10 + ch - '0';
|
|
}
|
|
|
|
index ++;
|
|
ch = text[index];
|
|
}
|
|
|
|
if (is_decimal)
|
|
{
|
|
while (decimal_len --)
|
|
{
|
|
num /= 10;
|
|
}
|
|
}
|
|
|
|
pushOperand(&stack_operand, num);
|
|
}
|
|
else
|
|
{
|
|
/* Push current operation to stack_operation when it's priority higher than the stack top operation. */
|
|
if ((stack_operation.top == -1) || !prior_compare(stack_operation.operation[stack_operation.top], ch))
|
|
{
|
|
pushOperation(&stack_operation, ch);
|
|
}
|
|
else
|
|
{
|
|
/* Pop out two operands and one operation and push the calculate result to stack_operand,
|
|
then push the current operation to the stack_operation. */
|
|
if (stack_operand.top < 1)
|
|
{
|
|
safe_string_copy(result, "Error Format", 100);
|
|
return;
|
|
}
|
|
|
|
popOperand(&stack_operand, &b);
|
|
popOperand(&stack_operand, &a);
|
|
popOperation(&stack_operation, &operation);
|
|
ans = calculate(a, operation, b);
|
|
|
|
pushOperand(&stack_operand, ans);
|
|
pushOperation(&stack_operation, ch);
|
|
}
|
|
index ++;
|
|
}
|
|
}
|
|
|
|
while (stack_operation.top >= 0)
|
|
{
|
|
if (stack_operand.top < 1)
|
|
{
|
|
safe_string_copy(result, "Error Format", 100);
|
|
return;
|
|
}
|
|
popOperand(&stack_operand, &b);
|
|
popOperand(&stack_operand, &a);
|
|
popOperation(&stack_operation, &operation);
|
|
ans = calculate(a, operation, b);
|
|
|
|
pushOperand(&stack_operand, ans);
|
|
}
|
|
|
|
/* Pop out evaluate result. */
|
|
popOperand(&stack_operand, &ans);
|
|
|
|
if (persent_flag)
|
|
{
|
|
ans /= 100;
|
|
}
|
|
|
|
/* Round to the 10th decimal. */
|
|
if(ans >= 0)
|
|
{
|
|
ans += 0.00000000005;
|
|
}
|
|
else
|
|
{
|
|
ans += -0.00000000005;
|
|
}
|
|
|
|
/* Save the calculation result to a char array. */
|
|
dtoa(ans);
|
|
}
|
|
|
|
double sw_pow(double a, int b)
|
|
{
|
|
double result = 1;
|
|
|
|
while (b--)
|
|
{
|
|
result *= a;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/* Convert a double value to an ASCII string. */
|
|
void dtoa(double ans)
|
|
{
|
|
INT digit_num = 1;
|
|
INT integer;
|
|
INT decimal[PRECISSION];
|
|
INT index = 0;
|
|
INT precision = PRECISSION;
|
|
double temp;
|
|
int result_index = 0;
|
|
int exponent = 0;
|
|
GX_BOOL exp = GX_FALSE;
|
|
|
|
if (ans < 0)
|
|
{
|
|
result[result_index++] = '-';
|
|
ans *= -1;
|
|
}
|
|
if (ans >= 10000000000000000.)
|
|
{
|
|
exp = GX_TRUE;
|
|
}
|
|
|
|
if(!exp)
|
|
{
|
|
/* Get integer number. */
|
|
temp = ans;
|
|
while(temp >= 10)
|
|
{
|
|
temp /= 10;
|
|
digit_num ++;
|
|
}
|
|
|
|
/* Save the integer part to 'result' array. */
|
|
if(digit_num > 1)
|
|
{
|
|
temp = sw_pow(10, digit_num - 1);
|
|
for (index = 0; index < digit_num; index++)
|
|
{
|
|
integer = (INT)(ans / temp);
|
|
result[result_index ++] = integer + '0';
|
|
ans -= integer * temp;
|
|
temp /= 10;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
integer = (INT)ans;
|
|
result[result_index ++] = integer + '0';
|
|
ans -= integer;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
while (ans >= 10)
|
|
{
|
|
ans /= 10;
|
|
exponent ++;
|
|
}
|
|
|
|
result[result_index ++] = (INT)ans + '0';
|
|
ans -= (INT)ans;
|
|
}
|
|
|
|
/* Save the decimal to 'decimal' array. */
|
|
for (index = 0; index < precision; index ++)
|
|
{
|
|
decimal[index] = (INT)(ans * 10);
|
|
ans = ans * 10 - decimal[index];
|
|
}
|
|
|
|
for (index = precision - 1; index >= 0; index --)
|
|
{
|
|
if (decimal[index] == 0)
|
|
{
|
|
precision --;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (precision)
|
|
{
|
|
result[result_index ++] = '.';
|
|
is_decimal_point = GX_TRUE;
|
|
}
|
|
else
|
|
{
|
|
is_decimal_point = GX_FALSE;
|
|
}
|
|
|
|
/* Save the decimal to 'result' array. */
|
|
for(index = 0; index < precision; index ++)
|
|
{
|
|
result[result_index++] = decimal[index] + '0';
|
|
}
|
|
|
|
if (!exp)
|
|
{
|
|
result[result_index] = '\0';
|
|
}
|
|
else
|
|
{
|
|
result[result_index ++] = 'E';
|
|
result[result_index ++] = '+';
|
|
gx_utility_ltoa(exponent, result + result_index, 3);
|
|
}
|
|
}
|