diff --git a/main/gbx/gbx_exec_loop.c b/main/gbx/gbx_exec_loop.c index 179bf1307..01d586e6c 100644 --- a/main/gbx/gbx_exec_loop.c +++ b/main/gbx/gbx_exec_loop.c @@ -76,7 +76,7 @@ static void *SubrTable[] = /* 28 */ _SUBR_comp, _SUBR_compn, SUBR_compi, SUBR_compi, /* 2C */ SUBR_compi, SUBR_compi, SUBR_near, SUBR_case, /* 30 */ _SUBR_add, _SUBR_sub, _SUBR_mul, _SUBR_div, - /* 34 */ SUBR_neg_, SUBR_quo, SUBR_rem, SUBR_pow, + /* 34 */ SUBR_neg, SUBR_quo, SUBR_rem, SUBR_pow, /* 38 */ SUBR_and_, SUBR_and_, SUBR_and_, SUBR_not, /* 3C */ SUBR_cat, SUBR_like, SUBR_file, SUBR_is, @@ -100,9 +100,9 @@ static void *SubrTable[] = SUBR_strcomp, /* 17 51 */ SUBR_iconv, /* 18 52 */ SUBR_sconv, /* 19 53 */ - SUBR_neg_, /* 20 54 */ - SUBR_neg_, /* 21 55 */ - SUBR_neg_, /* 22 56 */ + SUBR_abs, /* 20 54 */ + SUBR_int, /* 21 55 */ + SUBR_fix, /* 22 56 */ SUBR_sgn, /* 23 57 */ SUBR_math, /* 24 58 */ SUBR_pi, /* 25 59 */ @@ -469,7 +469,9 @@ _SUBR_CODE: _NEXT: - PC++; + PC++; + code = *PC; + goto *jump_table[code >> 8]; /*-----------------------------------------------*/ diff --git a/main/gbx/gbx_math.c b/main/gbx/gbx_math.c index ebc64def6..4d8ddaf4e 100644 --- a/main/gbx/gbx_math.c +++ b/main/gbx/gbx_math.c @@ -110,16 +110,6 @@ int fsgn(double x) return ((x > 0) ? 1 : ((x < 0) ? (-1) : 0)); } -double deg(double x) -{ - return x * 180 / M_PI; -} - -double rad(double x) -{ - return x * M_PI / 180; -} - double fix(double x) { if (x >= 0) diff --git a/main/gbx/gbx_math.h b/main/gbx/gbx_math.h index 5024587e8..c88c37862 100644 --- a/main/gbx/gbx_math.h +++ b/main/gbx/gbx_math.h @@ -33,8 +33,6 @@ int llsgn(int64_t x); double frac(double x); int fsgn(double x); -double deg(double x); -double rad(double x); double fix(double x); double frexp10(double x, int *exp); double ang(double x, double y); @@ -42,6 +40,9 @@ double ang(double x, double y); void randomize(bool set, uint seed); double rnd(void); +#define deg(_x) ((_x) * 180 / M_PI) +#define rad(_x) ((_x) * M_PI / 180) + #if defined(OS_FREEBSD) || defined(OS_OPENBSD) || defined(OS_CYGWIN) double exp10(double x); #ifdef log2 diff --git a/main/gbx/gbx_subr.h b/main/gbx/gbx_subr.h index 05f73961f..d8dce039a 100644 --- a/main/gbx/gbx_subr.h +++ b/main/gbx/gbx_subr.h @@ -104,7 +104,10 @@ void SUBR_pow(void); void SUBR_and_(ushort code); void SUBR_not(ushort code); -void SUBR_neg_(ushort code); +void SUBR_neg(ushort code); +void SUBR_int(ushort code); +void SUBR_abs(ushort code); +void SUBR_fix(ushort code); void SUBR_sgn(ushort code); void SUBR_pi(ushort code); void SUBR_math(ushort code); diff --git a/main/gbx/gbx_subr_math.c b/main/gbx/gbx_subr_math.c index 0d521af85..3921ee679 100644 --- a/main/gbx/gbx_subr_math.c +++ b/main/gbx/gbx_subr_math.c @@ -37,11 +37,11 @@ #define ABS(x) ((x) < 0 ? (-x) : (x)) -static MATH_FUNC MathFunc[] = { +/*static MATH_FUNC MathFunc[] = { NULL, frac, log, exp, sqrt, sin, cos, tan, atan, asin, acos, deg, rad, log10, sinh, cosh, tanh, asinh, acosh, atanh, exp2, exp10, log2, cbrt, expm1, log1p - }; + };*/ static MATH_FUNC_2 MathFunc2[] = { NULL, atan2, ang, hypot @@ -145,11 +145,45 @@ void SUBR_round(ushort code) void SUBR_math(ushort code) { + static void *jump[] = { + NULL, &&__FRAC, &&__LOG, &&__EXP, &&__SQRT, &&__SIN, &&__COS, &&__TAN, &&__ATAN, &&__ASIN, &&__ACOS, + &&__DEG, &&__RAD, &&__LOG10, &&__SINH, &&__COSH, &&__TANH, &&__ASINH, &&__ACOSH, &&__ATANH, + &&__EXP2, &&__EXP10, &&__LOG2, &&__CBRT, &&__EXPM1, &&__LOG1P + }; + + SUBR_ENTER_PARAM(1); VALUE_conv_float(PARAM); + goto *jump[code & 0x1F]; - PARAM->_float.value = (*MathFunc[code & 0x1F])(PARAM->_float.value); +__FRAC: PARAM->_float.value = frac(PARAM->_float.value); goto __END; +__LOG: PARAM->_float.value = log(PARAM->_float.value); goto __END; +__EXP: PARAM->_float.value = exp(PARAM->_float.value); goto __END; +__SQRT: PARAM->_float.value = sqrt(PARAM->_float.value); goto __END; +__SIN: PARAM->_float.value = sin(PARAM->_float.value); goto __END; +__COS: PARAM->_float.value = cos(PARAM->_float.value); goto __END; +__TAN: PARAM->_float.value = tan(PARAM->_float.value); goto __END; +__ATAN: PARAM->_float.value = atan(PARAM->_float.value); goto __END; +__ASIN: PARAM->_float.value = asin(PARAM->_float.value); goto __END; +__ACOS: PARAM->_float.value = acos(PARAM->_float.value); goto __END; +__DEG: PARAM->_float.value = deg(PARAM->_float.value); goto __END; +__RAD: PARAM->_float.value = rad(PARAM->_float.value); goto __END; +__LOG10: PARAM->_float.value = log10(PARAM->_float.value); goto __END; +__SINH: PARAM->_float.value = sinh(PARAM->_float.value); goto __END; +__COSH: PARAM->_float.value = cosh(PARAM->_float.value); goto __END; +__TANH: PARAM->_float.value = tanh(PARAM->_float.value); goto __END; +__ASINH: PARAM->_float.value = asinh(PARAM->_float.value); goto __END; +__ACOSH: PARAM->_float.value = acosh(PARAM->_float.value); goto __END; +__ATANH: PARAM->_float.value = atanh(PARAM->_float.value); goto __END; +__EXP2: PARAM->_float.value = exp2(PARAM->_float.value); goto __END; +__EXP10: PARAM->_float.value = exp10(PARAM->_float.value); goto __END; +__LOG2: PARAM->_float.value = log2(PARAM->_float.value); goto __END; +__CBRT: PARAM->_float.value = cbrt(PARAM->_float.value); goto __END; +__EXPM1: PARAM->_float.value = expm1(PARAM->_float.value); goto __END; +__LOG1P: PARAM->_float.value = log1p(PARAM->_float.value); goto __END; + +__END: if (!finite(PARAM->_float.value)) THROW(E_MATH); @@ -177,10 +211,34 @@ void SUBR_pow(void) SUBR_ENTER_PARAM(2); VALUE_conv_float(&PARAM[0]); - VALUE_conv_float(&PARAM[1]); + + if (TYPE_is_integer(PARAM[1].type)) + { + static void *jump[] = { &&__M4, &&__M3, &&__M2, &&__M1, &&__P0, &&__END, &&__P2, &&__P3, &&__P4 }; + int val = PARAM[1]._integer.value; + + if (val >= -4 && val <= 4) + goto *jump[val + 4]; + else + goto __FLOAT; + + __P0: PARAM->_float.value = 1.0; goto __END; + __P2: PARAM->_float.value *= PARAM->_float.value; goto __END; + __P3: PARAM->_float.value *= PARAM->_float.value * PARAM->_float.value; goto __END; + __P4: PARAM->_float.value *= PARAM->_float.value;PARAM->_float.value *= PARAM->_float.value; goto __END; + __M1: PARAM->_float.value = 1.0 / PARAM->_float.value; goto __END; + __M2: PARAM->_float.value = 1.0 / PARAM->_float.value / PARAM->_float.value; goto __END; + __M3: PARAM->_float.value = 1.0 / PARAM->_float.value / PARAM->_float.value / PARAM->_float.value; goto __END; + __M4: PARAM->_float.value = 1.0 / PARAM->_float.value / PARAM->_float.value / PARAM->_float.value / PARAM->_float.value; goto __END; + } +__FLOAT: + + VALUE_conv_float(&PARAM[1]); PARAM->_float.value = pow(PARAM[0]._float.value, PARAM[1]._float.value); +__END: + if (!finite(PARAM->_float.value)) THROW(E_MATH); @@ -407,6 +465,28 @@ __END: SP--; } +#define MANAGE_VARIANT(_func) \ +({ \ + type = P1->type; \ + \ + if (TYPE_is_number_date(type)) \ + { \ + *PC |= type; \ + goto *jump[type]; \ + } \ + \ + if (TYPE_is_variant(type)) \ + { \ + type = P1->_variant.vtype; \ + if (TYPE_is_number_date(type)) \ + { \ + VARIANT_undo(P1); \ + (_func)(code | type); \ + VALUE_conv_variant(P1); \ + return; \ + } \ + } \ +}) void SUBR_sgn(ushort code) @@ -460,6 +540,195 @@ __END: } +void SUBR_neg(ushort code) +{ + static void *jump[] = { + &&__VARIANT, &&__BOOLEAN, &&__BYTE, &&__SHORT, &&__INTEGER, &&__LONG, &&__SINGLE, &&__FLOAT, &&__ERROR + }; + + VALUE *P1; + TYPE type; + + P1 = SP - 1; + + type = code & 0x0F; + + goto *jump[type]; + +__BOOLEAN: + + return; + +__BYTE: + + P1->_integer.value = (unsigned char)(-P1->_integer.value); return; + +__SHORT: + + P1->_integer.value = (short)(-P1->_integer.value); return; + +__INTEGER: + + P1->_integer.value = (-P1->_integer.value); return; + +__LONG: + + P1->_long.value = (-P1->_long.value); return; + +__SINGLE: + + VALUE_conv_float(P1); + +__FLOAT: + + P1->_float.value = (-P1->_float.value); return; + +__VARIANT: + + MANAGE_VARIANT(SUBR_neg); + +__ERROR: + + THROW(E_TYPE, "Number", TYPE_get_name(type)); +} + + +void SUBR_abs(ushort code) +{ + static void *jump[] = { + &&__VARIANT, &&__BOOLEAN, &&__BYTE, &&__SHORT, &&__INTEGER, &&__LONG, &&__SINGLE, &&__FLOAT, &&__ERROR + }; + + VALUE *P1; + TYPE type; + + P1 = SP - 1; + + type = code & 0x0F; + + goto *jump[type]; + +__BOOLEAN: + + return; + +__BYTE: + + P1->_integer.value = (unsigned char)ABS(-P1->_integer.value); return; + +__SHORT: + + P1->_integer.value = (short)ABS(P1->_integer.value); return; + +__INTEGER: + + P1->_integer.value = ABS(P1->_integer.value); return; + +__LONG: + + P1->_long.value = ABS(P1->_long.value); return; + +__SINGLE: + + VALUE_conv_float(P1); + +__FLOAT: + + P1->_float.value = fabs(P1->_float.value); return; + +__VARIANT: + + MANAGE_VARIANT(SUBR_abs); + +__ERROR: + + THROW(E_TYPE, "Number", TYPE_get_name(type)); +} + + +void SUBR_int(ushort code) +{ + static void *jump[] = { + &&__VARIANT, &&__BOOLEAN, &&__BYTE, &&__SHORT, &&__INTEGER, &&__LONG, &&__SINGLE, &&__FLOAT, &&__ERROR + }; + + VALUE *P1; + TYPE type; + + P1 = SP - 1; + + type = code & 0x0F; + + goto *jump[type]; + +__BOOLEAN: +__BYTE: +__SHORT: +__INTEGER: +__LONG: + + return; + +__SINGLE: + + VALUE_conv_float(P1); + +__FLOAT: + + P1->_float.value = floor(P1->_float.value); return; + +__VARIANT: + + MANAGE_VARIANT(SUBR_int); + +__ERROR: + + THROW(E_TYPE, "Number", TYPE_get_name(type)); +} + + +void SUBR_fix(ushort code) +{ + static void *jump[] = { + &&__VARIANT, &&__BOOLEAN, &&__BYTE, &&__SHORT, &&__INTEGER, &&__LONG, &&__SINGLE, &&__FLOAT, &&__ERROR + }; + + VALUE *P1; + TYPE type; + + P1 = SP - 1; + + type = code & 0x0F; + + goto *jump[type]; + +__BOOLEAN: +__BYTE: +__SHORT: +__INTEGER: +__LONG: + + return; + +__SINGLE: + + VALUE_conv_float(P1); + +__FLOAT: + + P1->_float.value = fix(P1->_float.value); return; + +__VARIANT: + + MANAGE_VARIANT(SUBR_fix); + +__ERROR: + + THROW(E_TYPE, "Number", TYPE_get_name(type)); +} + + +#if 0 void SUBR_neg_(ushort code) { static void *jump[] = { @@ -585,8 +854,6 @@ __END: return; } - -#if 0 void SUBR_add_(ushort code) { static void *jump[] = {