[INTERPRETER]

* NEW: "_operators" is a new interface that allows any native class to be
  used with most of arithmetic operators: +, -, *, /, Abs, =, <> at the 
  moment.
* NEW: The "_convert" interface now allows a class to be converted to any
  datatype, not just other classes.
* NEW: Str() and Print uses the "_convert" interface to print a localized
  string conversion of any object.

[GB.GSL]
* NEW: Use the new "_operators" interface so that complex numbers can be 
  handled by standard arithmetic operators.
* NEW: The Complex class now implements the "_convert" interface.


git-svn-id: svn://localhost/gambas/trunk@4908 867c0c6c-44f3-4631-809d-bfa615b0a4ec
This commit is contained in:
Benoît Minisini 2012-07-08 14:35:58 +00:00
parent 2c631a0874
commit 7bd330aa00
12 changed files with 1495 additions and 140 deletions

View File

@ -38,20 +38,228 @@
#define THIS ((GSLCOMPLEX *)_object)
//---- Complex number creation ----------------------------------------------
/***********************************
Complex Utility Methods
***********************************/
GSLCOMPLEX *GSLComplex_create()
GSLCOMPLEX *COMPLEX_create()
{
static GB_CLASS _klass = (GB_CLASS)NULL;
GSLCOMPLEX *c;
c = (GSLCOMPLEX *)GB.New(GB.FindClass("Complex"), NULL, NULL);
if (!_klass)
_klass = GB.FindClass("Complex");
c = (GSLCOMPLEX *)GB.New(_klass, NULL, NULL);
c->number.dat[0] = 0.0;
c->number.dat[1] = 0.0;
return c;
}
//---- Arithmetic operators -------------------------------------------------
static GSLCOMPLEX *_addf(GSLCOMPLEX *a, double f)
{
GSLCOMPLEX *r = COMPLEX_create();
r->number = gsl_complex_add_real(a->number, f);
return r;
}
static GSLCOMPLEX *_add(GSLCOMPLEX *a, GSLCOMPLEX *b)
{
GSLCOMPLEX *r = COMPLEX_create();
r->number = gsl_complex_add(a->number, b->number);
return r;
}
static GSLCOMPLEX *_subf(GSLCOMPLEX *a, double f)
{
GSLCOMPLEX *r = COMPLEX_create();
r->number = gsl_complex_sub_real(a->number, f);
return r;
}
static GSLCOMPLEX *_sub(GSLCOMPLEX *a, GSLCOMPLEX *b)
{
GSLCOMPLEX *r = COMPLEX_create();
r->number = gsl_complex_sub(a->number, b->number);
return r;
}
static GSLCOMPLEX *_mulf(GSLCOMPLEX *a, double f)
{
GSLCOMPLEX *r = COMPLEX_create();
r->number = gsl_complex_mul_real(a->number, f);
return r;
}
static GSLCOMPLEX *_mul(GSLCOMPLEX *a, GSLCOMPLEX *b)
{
GSLCOMPLEX *r = COMPLEX_create();
r->number = gsl_complex_mul(a->number, b->number);
return r;
}
static GSLCOMPLEX *_divf(GSLCOMPLEX *a, double f)
{
gsl_complex c = gsl_complex_div_real(a->number, f);
if (isfinite(c.dat[0]) && isfinite(c.dat[1]))
{
GSLCOMPLEX *r = COMPLEX_create();
r->number = c;
return r;
}
else
return NULL;
}
static GSLCOMPLEX *_idivf(GSLCOMPLEX *a, double f)
{
GSLCOMPLEX *r = COMPLEX_create();
r->number = gsl_complex_mul_real(gsl_complex_inverse(a->number), f);
return r;
}
static GSLCOMPLEX *_div(GSLCOMPLEX *a, GSLCOMPLEX *b)
{
gsl_complex c = gsl_complex_div(a->number, b->number);
if (isfinite(c.dat[0]) && isfinite(c.dat[1]))
{
GSLCOMPLEX *r = COMPLEX_create();
r->number = c;
return r;
}
else
return NULL;
}
static int _equal(GSLCOMPLEX *a, GSLCOMPLEX *b)
{
return a->number.dat[0] == b->number.dat[0] && a->number.dat[1] == b->number.dat[1];
}
static int _equalf(GSLCOMPLEX *a, double f)
{
return a->number.dat[0] == f && a->number.dat[1] == 0.0;
}
static GSLCOMPLEX *_neg(GSLCOMPLEX *a)
{
GSLCOMPLEX *r = COMPLEX_create();
r->number = gsl_complex_negative(a->number);
return r;
}
static double _abs(GSLCOMPLEX *a)
{
return gsl_complex_abs(a->number);
}
static GB_OPERATOR_DESC _operators =
{
add: (void *)_add,
addf: (void *)_addf,
sub: (void *)_sub,
subf: (void *)_subf,
mul: (void *)_mul,
mulf: (void *)_mulf,
div: (void *)_div,
divf: (void *)_divf,
idivf: (void *)_idivf,
equal: (void *)_equal,
equalf: (void *)_equalf,
abs: (void *)_abs,
neg: (void *)_neg
};
//---- Conversions ----------------------------------------------------------
static char *_to_string(GSLCOMPLEX *_object, bool local)
{
char buffer[64];
char *p;
char *str;
int len;
double real, imag;
if (!THIS)
return NULL;
real = THIS->number.dat[0];
imag = THIS->number.dat[1];
if (real == 0.0 && imag == 0.0)
return GB.NewString("0", 1);
p = buffer;
if (real != 0.0)
{
GB.NumberToString(local, real, NULL, &str, &len);
strncpy(p, str, len);
p += len;
}
if (imag != 0.0)
{
if (imag < 0.0)
{
*p++ = '-';
imag = (-imag);
}
else if (p != buffer)
*p++ = '+';
if (imag != 1.0)
{
GB.NumberToString(local, imag, NULL, &str, &len);
strncpy(p, str, len);
p += len;
}
*p++ = 'i';
}
return GB.NewString(buffer, p - buffer);
}
static bool _convert(GSLCOMPLEX *a, GB_TYPE type, GB_VALUE *conv)
{
switch (type)
{
case GB_T_FLOAT:
conv->_float.value = gsl_complex_abs(a->number);
return FALSE;
case GB_T_SINGLE:
conv->_single.value = gsl_complex_abs(a->number);
return FALSE;
case GB_T_INTEGER:
case GB_T_SHORT:
case GB_T_BYTE:
conv->_integer.value = gsl_complex_abs(a->number);
return FALSE;
case GB_T_LONG:
conv->_long.value = gsl_complex_abs(a->number);
return FALSE;
case GB_T_STRING:
case GB_T_CSTRING:
conv->_string.value.addr = _to_string(a, type == GB_T_CSTRING);
conv->_string.value.start = 0;
conv->_string.value.len = GB.StringLength(conv->_string.value.addr);
return FALSE;
default:
return TRUE;
}
}
//---------------------------------------------------------------------------
BEGIN_METHOD(GslComplex_new, GB_FLOAT real; GB_FLOAT imag)
THIS->number.dat[0] = VARGOPT(real, 0.0);
@ -62,7 +270,7 @@ END_METHOD
BEGIN_METHOD(GslComplex_call, GB_FLOAT real; GB_FLOAT imag)
GSLCOMPLEX *c = GSLComplex_create();
GSLCOMPLEX *c = COMPLEX_create();
c->number.dat[0] = VARG(real);
c->number.dat[1] = VARG(imag);
@ -73,7 +281,7 @@ END_METHOD
BEGIN_METHOD_VOID(GslComplex_Copy)
GSLCOMPLEX *c = GSLComplex_create();
GSLCOMPLEX *c = COMPLEX_create();
c->number = THIS->number;
GB.ReturnObject(c);
@ -110,15 +318,11 @@ BEGIN_METHOD_VOID(GslComplex_ToString)
{
if (imag < 0.0)
{
*p++ = ' ';
*p++ = '-';
*p++ = ' ';
imag = (-imag);
}
else if (p != buffer)
*p++ = ' ';
*p++ = '+';
*p++ = ' ';
if (imag != 1.0)
{
@ -233,7 +437,7 @@ BEGIN_METHOD(GslComplex_Add, GB_OBJECT x)
return;
// Create new object
obj = GSLComplex_create();
obj = COMPLEX_create();
// Add two complex numbers
obj->number = gsl_complex_add(THIS->number, x->number);
@ -251,7 +455,7 @@ BEGIN_METHOD(GslComplex_Sub, GB_OBJECT x)
if (GB.CheckObject(x))
return;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_sub(THIS->number, x->number);
@ -268,7 +472,7 @@ BEGIN_METHOD(GslComplex_Mul, GB_OBJECT x)
if (GB.CheckObject(x))
return;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_mul(THIS->number, x->number);
@ -285,7 +489,7 @@ BEGIN_METHOD(GslComplex_Div, GB_OBJECT x)
if (GB.CheckObject(x))
return;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_div(THIS->number, x->number);
@ -301,7 +505,7 @@ BEGIN_METHOD(GslComplex_Add_Real, GB_FLOAT x)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_add_real(THIS->number, VARG(x));
@ -314,7 +518,7 @@ BEGIN_METHOD(GslComplex_Sub_Real, GB_FLOAT x)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_sub_real(THIS->number, VARG(x));
@ -327,7 +531,7 @@ BEGIN_METHOD(GslComplex_Mul_Real, GB_FLOAT x)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_mul_real(THIS->number, VARG(x));
@ -340,7 +544,7 @@ BEGIN_METHOD(GslComplex_Div_Real, GB_FLOAT x)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_div_real(THIS->number, VARG(x));
@ -356,7 +560,7 @@ BEGIN_METHOD(GslComplex_Add_Imag, GB_FLOAT x)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_add_imag(THIS->number, VARG(x));
@ -369,7 +573,7 @@ BEGIN_METHOD(GslComplex_Sub_Imag, GB_FLOAT x)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_sub_imag(THIS->number, VARG(x));
@ -382,7 +586,7 @@ BEGIN_METHOD(GslComplex_Mul_Imag, GB_FLOAT x)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_mul_imag(THIS->number, VARG(x));
@ -395,7 +599,7 @@ BEGIN_METHOD(GslComplex_Div_Imag, GB_FLOAT x)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_div_imag(THIS->number, VARG(x));
@ -408,7 +612,7 @@ BEGIN_METHOD_VOID(GslComplex_Conjugate)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_conjugate(THIS->number);
@ -420,7 +624,7 @@ BEGIN_METHOD_VOID(GslComplex_Inverse)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_inverse(THIS->number);
@ -433,7 +637,7 @@ BEGIN_METHOD_VOID(GslComplex_Negative)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_negative(THIS->number);
@ -449,7 +653,7 @@ BEGIN_METHOD_VOID(GslComplex_Sqrt)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_sqrt(THIS->number);
@ -462,7 +666,7 @@ BEGIN_METHOD(GslComplex_SqrtReal, GB_FLOAT x;)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_sqrt_real(VARG(x));
@ -479,7 +683,7 @@ BEGIN_METHOD(GslComplex_Pow, GB_OBJECT x;)
if (GB.CheckObject(x))
return;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_pow(THIS->number, x->number);
@ -492,7 +696,7 @@ BEGIN_METHOD(GslComplex_PowReal, GB_FLOAT x;)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_pow_real(THIS->number, VARG(x));
@ -505,7 +709,7 @@ BEGIN_METHOD_VOID(GslComplex_Exp)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_exp(THIS->number);
@ -518,7 +722,7 @@ BEGIN_METHOD_VOID(GslComplex_Log)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_log(THIS->number);
@ -531,7 +735,7 @@ BEGIN_METHOD_VOID(GslComplex_Log10)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_log10(THIS->number);
@ -548,7 +752,7 @@ BEGIN_METHOD(GslComplex_Log_b, GB_OBJECT x;)
if (GB.CheckObject(x))
return;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_log_b(THIS->number, x->number);
@ -566,7 +770,7 @@ BEGIN_METHOD_VOID(GslComplex_Sin)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_sin(THIS->number);
@ -579,7 +783,7 @@ BEGIN_METHOD_VOID(GslComplex_Cos)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_cos(THIS->number);
@ -592,7 +796,7 @@ BEGIN_METHOD_VOID(GslComplex_Tan)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_tan(THIS->number);
@ -605,7 +809,7 @@ BEGIN_METHOD_VOID(GslComplex_Sec)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_sec(THIS->number);
@ -618,7 +822,7 @@ BEGIN_METHOD_VOID(GslComplex_Csc)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_csc(THIS->number);
@ -631,7 +835,7 @@ BEGIN_METHOD_VOID(GslComplex_Cot)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_cot(THIS->number);
@ -648,7 +852,7 @@ END_METHOD
BEGIN_METHOD_VOID(GslComplex_Arcsin)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_arcsin(THIS->number);
@ -661,7 +865,7 @@ BEGIN_METHOD(GslComplex_Arcsin_Real, GB_FLOAT x;)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_arcsin_real(VARG(x));
@ -673,7 +877,7 @@ END_METHOD
BEGIN_METHOD_VOID(GslComplex_Arccos)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_arccos(THIS->number);
@ -686,7 +890,7 @@ BEGIN_METHOD(GslComplex_Arccos_Real, GB_FLOAT x;)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_arccos_real(VARG(x));
@ -698,7 +902,7 @@ END_METHOD
BEGIN_METHOD_VOID(GslComplex_Arctan)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_arctan(THIS->number);
@ -710,7 +914,7 @@ END_METHOD
BEGIN_METHOD_VOID(GslComplex_Arcsec)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_arcsec(THIS->number);
@ -723,7 +927,7 @@ BEGIN_METHOD(GslComplex_Arcsec_Real, GB_FLOAT x;)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_arcsec_real(VARG(x));
@ -735,7 +939,7 @@ END_METHOD
BEGIN_METHOD_VOID(GslComplex_Arccsc)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_arccsc(THIS->number);
@ -748,7 +952,7 @@ BEGIN_METHOD(GslComplex_Arccsc_Real, GB_FLOAT x;)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_arccsc_real(VARG(x));
@ -760,7 +964,7 @@ END_METHOD
BEGIN_METHOD_VOID(GslComplex_Arccot)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_arccot(THIS->number);
@ -777,7 +981,7 @@ END_METHOD
BEGIN_METHOD_VOID(GslComplex_Sinh)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_sinh(THIS->number);
@ -789,7 +993,7 @@ END_METHOD
BEGIN_METHOD_VOID(GslComplex_Cosh)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_cosh(THIS->number);
@ -801,7 +1005,7 @@ END_METHOD
BEGIN_METHOD_VOID(GslComplex_Tanh)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_tanh(THIS->number);
@ -813,7 +1017,7 @@ END_METHOD
BEGIN_METHOD_VOID(GslComplex_Sech)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_sech(THIS->number);
@ -825,7 +1029,7 @@ END_METHOD
BEGIN_METHOD_VOID(GslComplex_Csch)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_csch(THIS->number);
@ -837,7 +1041,7 @@ END_METHOD
BEGIN_METHOD_VOID(GslComplex_Coth)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_coth(THIS->number);
@ -854,7 +1058,7 @@ END_METHOD
BEGIN_METHOD_VOID(GslComplex_Arcsinh)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_arcsinh(THIS->number);
@ -866,7 +1070,7 @@ END_METHOD
BEGIN_METHOD_VOID(GslComplex_Arccosh)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_arccosh(THIS->number);
@ -879,7 +1083,7 @@ BEGIN_METHOD(GslComplex_Arccosh_Real, GB_FLOAT x;)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_arccosh_real(VARG(x));
@ -891,7 +1095,7 @@ END_METHOD
BEGIN_METHOD_VOID(GslComplex_Arctanh)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_arctanh(THIS->number);
@ -904,7 +1108,7 @@ BEGIN_METHOD(GslComplex_Arctanh_Real, GB_FLOAT x;)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_arctanh_real(VARG(x));
@ -917,7 +1121,7 @@ END_METHOD
BEGIN_METHOD_VOID(GslComplex_Arcsech)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_arcsech(THIS->number);
@ -929,7 +1133,7 @@ END_METHOD
BEGIN_METHOD_VOID(GslComplex_Arccsch)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_arccsch(THIS->number);
@ -941,7 +1145,7 @@ END_METHOD
BEGIN_METHOD_VOID(GslComplex_Arccoth)
GSLCOMPLEX *obj;
obj = GSLComplex_create();
obj = COMPLEX_create();
obj->number = gsl_complex_arccoth(THIS->number);
@ -967,15 +1171,17 @@ GB_DESC CComplexDesc[] =
GB_METHOD("Rect", NULL, GslComplex_Rect, "[(Real)f(Imag)f]"),
GB_METHOD("Polar", NULL, GslComplex_Polar, "[(Real)f(Imag)f]"),
GB_METHOD("Arg", "f", GslComplex_Arg, NULL),
GB_INTERFACE("_operators", &_operators),
GB_INTERFACE("_convert", &_convert),
GB_METHOD("Abs", "f", GslComplex_Abs, NULL),
GB_METHOD("Abs2", "f", GslComplex_Abs2, NULL),
GB_METHOD("LogAbs", "f", GslComplex_LogAbs, NULL),
// Properties
GB_PROPERTY("Real", "f", GslComplex_Real),
GB_PROPERTY("Imag", "f", GslComplex_Imagined),
/* Operations on gsl_complex */
// Elementary Math Functions

View File

@ -1,25 +1,25 @@
/***************************************************************************
c_complex.h
c_complex.h
gb.gsl component
gb.gsl component
(c) 2012 Randall Morgan <rmorgan62@gmail.com>
(c) 2012 Randall Morgan <rmorgan62@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
***************************************************************************/
@ -38,14 +38,13 @@ GB_INTERFACE GB EXPORT;
extern GB_DESC CComplexDesc[];
typedef
struct __GSLCOMPLEX
{
GB_BASE ob;
gsl_complex number;
}
GSLCOMPLEX;
GSLCOMPLEX *GSLComplex_create();
struct
{
GB_BASE ob;
gsl_complex number;
}
GSLCOMPLEX;
GSLCOMPLEX *COMPLEX_create();
#endif /* __C_GSL_COMPLEX_H */

View File

@ -228,7 +228,7 @@ BEGIN_METHOD_VOID(CComplexPolynomial_ComplexSolve)
for(i = 0; i < THIS->len-1; i++)
{
printf ("z%d = %+.18f %+.18f\n", i, GSL_REAL(z[i]), GSL_IMAG(z[i]));
cx = GSLComplex_create();
cx = COMPLEX_create();
if(cx)
{
GSLCOMPLEX *elt;

View File

@ -1400,15 +1400,15 @@ static void error_array_convert()
OBJECT_UNREF(_converted_array, "error_array_convert");
}
static void *array_convert(CARRAY *src, CLASS *class)
static bool array_convert(CARRAY *src, CLASS *class, VALUE *conv)
{
CARRAY *array;
int i;
void *data;
VALUE temp;
if (!CLASS_inherits(class, CLASS_Array))
return NULL;
if (!TYPE_is_pure_object((TYPE)class) || !CLASS_inherits(class, CLASS_Array))
return TRUE;
_converted_array = array = OBJECT_create(class, NULL, NULL, 0);
@ -1429,7 +1429,9 @@ static void *array_convert(CARRAY *src, CLASS *class)
}
END_ERROR
return array;
conv->_object.object = array;
OBJECT_REF(array, "array_convert");
return FALSE;
}
#else

View File

@ -1266,6 +1266,8 @@ void *CLASS_auto_create(CLASS *class, int nparam)
void CLASS_search_special(CLASS *class)
{
int sym;
class->special[SPEC_NEW] = CLASS_get_symbol_index_kind(class, "_new", CD_METHOD, 0);
class->special[SPEC_FREE] = CLASS_get_symbol_index_kind(class, "_free", CD_METHOD, 0);
class->special[SPEC_GET] = CLASS_get_symbol_index_kind(class, "_get", CD_METHOD, CD_STATIC_METHOD);
@ -1279,7 +1281,15 @@ void CLASS_search_special(CLASS *class)
class->special[SPEC_ATTACH] = CLASS_get_symbol_index_kind(class, "_attach", CD_METHOD, 0);
class->special[SPEC_CONVERT] = CLASS_get_symbol_index_kind(class, "_@_convert", CD_CONSTANT, 0);
class->has_convert = class->special[SPEC_CONVERT] != NO_SYMBOL;
sym = CLASS_get_symbol_index_kind(class, "_@_operators", CD_CONSTANT, 0);
if (sym != NO_SYMBOL)
{
class->has_operators = TRUE;
class->operators = CLASS_get_desc(class, sym)->constant.value._pointer;
}
if (class->special[SPEC_NEXT] != NO_SYMBOL)
class->enum_static = CLASS_DESC_get_type(CLASS_get_desc(class, class->special[SPEC_NEXT])) == CD_STATIC_METHOD;
if (class->special[SPEC_UNKNOWN] != NO_SYMBOL)

View File

@ -238,6 +238,28 @@ enum
CS_READY = 2
};
enum {
CO_EQUAL,
CO_EQUALF,
CO_COMP,
CO_COMPF,
CO_ADD,
CO_ADDF,
CO_SUB,
CO_SUBF,
CO_MUL,
CO_MULF,
CO_DIV,
CO_DIVF,
CO_IDIVF,
CO_NEG,
CO_POW,
CO_POWF,
CO_ABS,
CO_MAX,
CO_MIN
};
typedef
struct _CLASS { // 32b 64b
struct _CLASS *class; // 4 8 Points at the 'Class' class !
@ -271,9 +293,11 @@ typedef
unsigned init_dynamic : 1; // If there is a special function to call at instanciation
unsigned must_check : 1; // The class has a check function
unsigned has_child : 1; // The class has an inherited child class
unsigned unknown_static : 1; // if _unknown is static
unsigned unknown_static : 1; // if _unknown is static
unsigned property_static : 1; // if _property is static
unsigned _reserved : 3; // 24 36
unsigned has_convert : 1; // if the _convert interface is implemented
unsigned has_operators : 1; // if the _operators interface is implemented
unsigned _reserved : 1; // 24 36
short n_desc; // 26 38 number of descriptions
short n_event; // 28 40 number of events
@ -309,17 +333,18 @@ typedef
struct _CLASS *astruct_class; // 112 176 array of struct class
void *instance; // 116 184 automatically created instance
void *operators; // 120 192 arithmetic interface
COMPONENT *component; // 120 192 The component the class belongs to
COMPONENT *component; // 124 200 The component the class belongs to
struct _CLASS *override; // 124 200 The overridden class
struct _CLASS *override; // 128 208 The overridden class
struct _CLASS *next; // 128 208 next class
struct _CLASS *next; // 132 216 next class
void (**jit_functions)(void); // 132 216 array of jit functions
void (**jit_functions)(void); // 136 224 array of jit functions
}
CLASS;
typedef
struct {
SYMBOL sym;

View File

@ -73,6 +73,8 @@ static void _SUBR_sub(ushort code);
static void _SUBR_mul(ushort code);
static void _SUBR_div(ushort code);
//---- Subroutine dispatch table --------------------------------------------
static void *SubrTable[] =
{
/* 28 */ NULL, _SUBR_compn, _SUBR_compi, _SUBR_compi,
@ -181,6 +183,139 @@ static void *SubrTable[] =
};
//---- Object arithmetic helpers --------------------------------------------
#define OP_NONE 0
#define OP_OBJECT_FLOAT 1
#define OP_FLOAT_OBJECT 2
#define OP_OBJECT_CONV 3
#define OP_CONV_OBJECT 4
#define OP_OBJECT 5
static int check_operators(VALUE *P1, VALUE *P2)
{
if (TYPE_is_number(P1->type) && TYPE_is_object(P2->type))
{
if (OBJECT_class(P2->_object.object)->has_operators)
{
//*dynamic = P2->type == T_OBJECT;
return OP_FLOAT_OBJECT;
}
}
else if (TYPE_is_number(P2->type) && TYPE_is_object(P1->type))
{
if (OBJECT_class(P1->_object.object)->has_operators)
{
//*dynamic = P1->type == T_OBJECT;
return OP_OBJECT_FLOAT;
}
}
else if (TYPE_is_object(P1->type) && TYPE_is_object(P2->type))
{
CLASS *class1 = OBJECT_class(P1->_object.object);
CLASS *class2 = OBJECT_class(P2->_object.object);
//*dynamic = P1->type == T_OBJECT || P2->type = T_OBJECT;
if (class1 && class1->has_operators)
{
if (class1 == class2)
return OP_OBJECT;
if (class2 && class2->has_operators)
return OP_OBJECT_CONV;
}
}
return OP_NONE;
}
static void operator_object_float(VALUE *P1, VALUE *P2, uchar op)
{
void *(*func)(void *, double) = (void *(*)(void *, double))((void **)(OBJECT_class(P1->_object.object)->operators))[op];
VALUE_conv_float(P2);
void *result = (*func)(P1->_object.object, P2->_float.value);
OBJECT_REF(result, "operator_object_float");
OBJECT_UNREF(P1->_object.object, "operator_object_float");
P1->_object.object = result;
}
static void operator_float_object(VALUE *P1, VALUE *P2, uchar op)
{
void *(*func)(void *, double) = (void *(*)(void *, double))((void **)(OBJECT_class(P2->_object.object)->operators))[op];
VALUE_conv_float(P1);
void *result = (*func)(P2->_object.object, P1->_float.value);
OBJECT_REF(result, "operator_float_object");
P1->_object.class = P2->_object.class;
OBJECT_UNREF(P2->_object.object, "operator_float_object");
P1->_object.object = result;
}
static void operator_object(VALUE *P1, VALUE *P2, uchar op)
{
void *(*func)(void *, void *) = (void *(*)(void *, void *))((void **)(OBJECT_class(P1->_object.object)->operators))[op];
void *result = (*func)(P1->_object.object, P2->_object.object);
OBJECT_REF(result, "operator_object");
OBJECT_UNREF(P1->_object.object, "operator_object");
OBJECT_UNREF(P2->_object.object, "operator_object");
P1->_object.object = result;
}
static void operator_object_conv(VALUE *P1, VALUE *P2, char op)
{
VALUE_conv(P2, (TYPE)P1->_object.class);
operator_object(P1, P2, op);
}
static void operator_conv_object(VALUE *P1, VALUE *P2, char op)
{
VALUE_conv(P1, (TYPE)P2->_object.class);
operator_object(P1, P2, op);
}
static int comparator_object_float(VALUE *P1, VALUE *P2, uchar op)
{
int (*func)(void *, double) = (int (*)(void *, double))((void **)(OBJECT_class(P1->_object.object)->operators))[op];
VALUE_conv_float(P2);
int result = (*func)(P1->_object.object, P2->_float.value);
OBJECT_UNREF(P1->_object.object, "comparator_object_float");
return result;
}
static int comparator_float_object(VALUE *P1, VALUE *P2, uchar op)
{
int (*func)(void *, double) = (int (*)(void *, double))((void **)(OBJECT_class(P2->_object.object)->operators))[op];
VALUE_conv_float(P1);
int result = (*func)(P2->_object.object, P1->_float.value);
OBJECT_UNREF(P2->_object.object, "comparator_float_object");
return result;
}
static int comparator_object(VALUE *P1, VALUE *P2, uchar op)
{
int (*func)(void *, void *) = (int (*)(void *, void *))((void **)(OBJECT_class(P1->_object.object)->operators))[op];
int result = (*func)(P1->_object.object, P2->_object.object);
OBJECT_UNREF(P1->_object.object, "comparator_object");
OBJECT_UNREF(P2->_object.object, "comparator_object");
return result;
}
static int comparator_object_conv(VALUE *P1, VALUE *P2, char op)
{
VALUE_conv(P2, (TYPE)P1->_object.class);
return comparator_object(P1, P2, op);
}
static int comparator_conv_object(VALUE *P1, VALUE *P2, char op)
{
VALUE_conv(P1, (TYPE)P2->_object.class);
return comparator_object(P1, P2, op);
}
//---- Main interpreter loop ------------------------------------------------
void EXEC_loop(void)
{
static const void *jump_table[256] =
@ -1707,14 +1842,14 @@ _ADD_QUICK:
if (LIKELY(type <= T_POINTER))
goto *_aq_jump[type];
__AQ_VOID:
THROW(E_NRETURN);
__AQ_BOOLEAN:
THROW(E_TYPE, "Number", TYPE_get_name(type));
__AQ_VOID:
THROW(E_NRETURN);
__AQ_BYTE:
P1->_integer.value = (unsigned char)(P1->_integer.value + value);
@ -2041,9 +2176,10 @@ _SUBR_LEN:
_SUBR_COMP:
{
static void *jump[17] = {
static void *jump[] = {
&&__SC_VARIANT, &&__SC_BOOLEAN, &&__SC_BYTE, &&__SC_SHORT, &&__SC_INTEGER, &&__SC_LONG, &&__SC_SINGLE, &&__SC_FLOAT, &&__SC_DATE,
&&__SC_STRING, &&__SC_STRING, &&__SC_POINTER, &&__SC_ERROR, &&__SC_ERROR, &&__SC_ERROR, &&__SC_NULL, &&__SC_OBJECT
&&__SC_STRING, &&__SC_STRING, &&__SC_POINTER, &&__SC_ERROR, &&__SC_ERROR, &&__SC_ERROR, &&__SC_NULL, &&__SC_OBJECT,
&&__SC_OBJECT_FLOAT, &&__SC_FLOAT_OBJECT, &&__SC_OBJECT_CONV, &&__SC_CONV_OBJECT, &&__SC_OBJECT_OBJECT
};
char NO_WARNING(result);
@ -2137,6 +2273,31 @@ _SUBR_COMP:
//RELEASE_OBJECT(P2);
goto __SC_END_RELEASE;
__SC_OBJECT_FLOAT:
result = comparator_object_float(P1, P2, CO_EQUALF);
goto __SC_END;
__SC_FLOAT_OBJECT:
result = comparator_float_object(P1, P2, CO_EQUALF);
goto __SC_END;
__SC_OBJECT_CONV:
result = comparator_object_conv(P1, P2, CO_EQUAL);
goto __SC_END;
__SC_CONV_OBJECT:
result = comparator_conv_object(P1, P2, CO_EQUAL);
goto __SC_END;
__SC_OBJECT_OBJECT:
result = comparator_object(P1, P2, CO_EQUAL);
goto __SC_END;
__SC_VARIANT:
{
@ -2155,6 +2316,15 @@ _SUBR_COMP:
variant = TRUE;
}
code = check_operators(P1, P2);
if (code)
{
code += T_OBJECT;
if (!(variant || P1->type == T_OBJECT || P2->type == T_OBJECT))
*PC |= code;
goto *jump[code];
}
type = Max(P1->type, P2->type);
if (TYPE_is_object_null(P1->type) && TYPE_is_object_null(P2->type))
@ -2345,9 +2515,10 @@ __END:
static void _SUBR_compn(ushort code)
{
static void *jump[17] = {
static void *jump[] = {
&&__VARIANT, &&__BOOLEAN, &&__BYTE, &&__SHORT, &&__INTEGER, &&__LONG, &&__SINGLE, &&__FLOAT, &&__DATE,
&&__STRING, &&__STRING, &&__POINTER, &&__ERROR, &&__ERROR, &&__ERROR, &&__NULL, &&__OBJECT
&&__STRING, &&__STRING, &&__POINTER, &&__ERROR, &&__ERROR, &&__ERROR, &&__NULL, &&__OBJECT,
&&__OBJECT_FLOAT, &&__FLOAT_OBJECT, &&__OBJECT_CONV, &&__CONV_OBJECT, &&__OBJECT_OBJECT
};
//static void *test[] = { &&__EQ, &&__NE, &&__GT, &&__LE, &&__LT, &&__GE };
@ -2443,6 +2614,31 @@ __OBJECT:
//RELEASE_OBJECT(P2);
goto __END_RELEASE;
__OBJECT_FLOAT:
result = comparator_object_float(P1, P2, CO_EQUALF);
goto __END;
__FLOAT_OBJECT:
result = comparator_float_object(P1, P2, CO_EQUALF);
goto __END;
__OBJECT_CONV:
result = comparator_object_conv(P1, P2, CO_EQUAL);
goto __END;
__CONV_OBJECT:
result = comparator_conv_object(P1, P2, CO_EQUAL);
goto __END;
__OBJECT_OBJECT:
result = comparator_object(P1, P2, CO_EQUAL);
goto __END;
__VARIANT:
{
@ -2461,6 +2657,15 @@ __VARIANT:
variant = TRUE;
}
code = check_operators(P1, P2);
if (code)
{
code += T_OBJECT;
if (!(variant || P1->type == T_OBJECT || P2->type == T_OBJECT))
*PC |= code;
goto *jump[code];
}
type = Max(P1->type, P2->type);
if (TYPE_is_object_null(P1->type) && TYPE_is_object_null(P2->type))
@ -2493,7 +2698,7 @@ __END:
P1->_boolean.value = result - 1; // ? 0 : -1;
}
#define sgn(_x) \
/*#define sgn(_x) \
({ \
int x = _x; \
int minusOne = x >> 31; \
@ -2501,13 +2706,653 @@ __END:
int plusOne = (int)(negateX >> 31); \
int result = minusOne | plusOne; \
result; \
})
})*/
static void my_VALUE_class_constant(CLASS *class, VALUE *value, int ind)
{
VALUE_class_constant_inline(class, value, ind);
}
#define STATIC_SUBR
#include "gbx_subr_common.h"
#define MANAGE_VARIANT_OBJECT(_func) \
({ \
type = Max(P1->type, P2->type); \
if (TYPE_is_void(P1->type) || TYPE_is_void(P2->type)) \
THROW(E_NRETURN); \
\
if (TYPE_is_number_date(type)) \
{ \
*PC |= type; \
goto *jump[type]; \
} \
\
code = check_operators(P1, P2); \
if (code) \
{ \
code += T_DATE; \
if (!(P1->type == T_OBJECT || P2->type == T_OBJECT)) \
*PC |= code; \
goto *jump[code]; \
} \
\
VARIANT_undo(P1); \
VARIANT_undo(P2); \
\
if (TYPE_is_string(P1->type)) \
VALUE_conv_float(P1); \
\
if (TYPE_is_string(P2->type)) \
VALUE_conv_float(P2); \
\
if (TYPE_is_null(P1->type) || TYPE_is_null(P2->type)) \
type = T_NULL; \
else \
type = Max(P1->type, P2->type); \
\
if (TYPE_is_number_date(type)) \
{ \
(_func)(code | type); \
VALUE_conv_variant(P1); \
return; \
} \
\
code = check_operators(P1, P2); \
if (code) \
{ \
(_func)(code + T_DATE); \
VALUE_conv_variant(P1); \
return; \
} \
})
#define MANAGE_VARIANT_POINTER_OBJECT(_func) \
({ \
type = Max(P1->type, P2->type); \
if (TYPE_is_void(P1->type) || TYPE_is_void(P2->type)) \
THROW(E_NRETURN); \
\
if (TYPE_is_number_date(type) || TYPE_is_pointer(type)) \
{ \
*PC |= type; \
goto *jump[type]; \
} \
\
code = check_operators(P1, P2); \
if (code) \
{ \
code += T_POINTER; \
*PC |= code; \
goto *jump[code]; \
} \
\
VARIANT_undo(P1); \
VARIANT_undo(P2); \
\
if (TYPE_is_string(P1->type)) \
VALUE_conv_float(P1); \
\
if (TYPE_is_string(P2->type)) \
VALUE_conv_float(P2); \
\
if (TYPE_is_null(P1->type) || TYPE_is_null(P2->type)) \
type = T_NULL; \
else \
type = Max(P1->type, P2->type); \
\
if (TYPE_is_number_date(type) || TYPE_is_pointer(type)) \
{ \
(_func)(code | type); \
VALUE_conv_variant(P1); \
return; \
} \
\
code = check_operators(P1, P2); \
if (code) \
{ \
(_func)(code + T_POINTER); \
VALUE_conv_variant(P1); \
return; \
} \
})
static void _SUBR_add(ushort code)
{
static void *jump[] = {
&&__VARIANT, &&__BOOLEAN, &&__BYTE, &&__SHORT, &&__INTEGER, &&__LONG, &&__SINGLE, &&__FLOAT, &&__DATE, NULL, NULL, &&__POINTER,
&&__OBJECT_FLOAT, &&__FLOAT_OBJECT, &&__OBJECT_CONV, &&__CONV_OBJECT, &&__OBJECT
};
TYPE type;
VALUE *P1, *P2;
P1 = SP - 2;
P2 = P1 + 1;
type = code & 0x0F;
goto *jump[type];
__BOOLEAN:
P1->type = T_BOOLEAN;
P1->_integer.value = P1->_integer.value | P2->_integer.value; goto __END;
__BYTE:
P1->type = T_BYTE;
P1->_integer.value = (unsigned char)(P1->_integer.value + P2->_integer.value); goto __END;
__SHORT:
P1->type = T_SHORT;
P1->_integer.value = (short)(P1->_integer.value + P2->_integer.value); goto __END;
__INTEGER:
P1->type = T_INTEGER;
P1->_integer.value += P2->_integer.value; goto __END;
__LONG:
VALUE_conv(P1, T_LONG);
VALUE_conv(P2, T_LONG);
P1->_long.value += P2->_long.value; goto __END;
__SINGLE:
VALUE_conv(P1, T_SINGLE);
VALUE_conv(P2, T_SINGLE);
P1->_single.value += P2->_single.value; goto __END;
__DATE:
__FLOAT:
VALUE_conv_float(P1);
VALUE_conv_float(P2);
P1->_float.value += P2->_float.value;
//fprintf(stderr, "+: %.24g\n", P1->_float.value);
goto __END;
__POINTER:
VALUE_conv(P1, T_POINTER);
VALUE_conv(P2, T_POINTER);
P1->_pointer.value += (intptr_t)P2->_pointer.value; goto __END;
__OBJECT_FLOAT:
operator_object_float(P1, P2, CO_ADDF);
goto __END;
__FLOAT_OBJECT:
operator_float_object(P1, P2, CO_ADDF);
goto __END;
__OBJECT_CONV:
operator_object_conv(P1, P2, CO_ADD);
goto __END;
__CONV_OBJECT:
operator_conv_object(P1, P2, CO_ADD);
goto __END;
__OBJECT:
operator_object(P1, P2, CO_ADD);
goto __END;
__VARIANT:
MANAGE_VARIANT_POINTER_OBJECT(_SUBR_add);
goto __ERROR;
__ERROR:
THROW(E_TYPE, "Number", TYPE_get_name(type));
__END:
SP--;
}
static void _SUBR_sub(ushort code)
{
static void *jump[] = {
&&__VARIANT, &&__BOOLEAN, &&__BYTE, &&__SHORT, &&__INTEGER, &&__LONG, &&__SINGLE, &&__FLOAT, &&__DATE, NULL, NULL, &&__POINTER,
&&__OBJECT_FLOAT, &&__FLOAT_OBJECT, &&__OBJECT_CONV, &&__CONV_OBJECT, &&__OBJECT
};
TYPE type;
VALUE *P1, *P2;
P1 = SP - 2;
P2 = P1 + 1;
type = code & 0x0F;
goto *jump[type];
__BOOLEAN:
P1->type = T_BOOLEAN;
P1->_integer.value = P1->_integer.value ^ P2->_integer.value; goto __END;
__BYTE:
P1->type = T_BYTE;
P1->_integer.value = (unsigned char)(P1->_integer.value - P2->_integer.value); goto __END;
__SHORT:
P1->type = T_SHORT;
P1->_integer.value = (short)(P1->_integer.value - P2->_integer.value); goto __END;
__INTEGER:
P1->type = T_INTEGER;
P1->_integer.value -= P2->_integer.value; goto __END;
__LONG:
VALUE_conv(P1, T_LONG);
VALUE_conv(P2, T_LONG);
P1->_long.value -= P2->_long.value; goto __END;
__SINGLE:
VALUE_conv(P1, T_SINGLE);
VALUE_conv(P2, T_SINGLE);
P1->_single.value -= P2->_single.value; goto __END;
__DATE:
__FLOAT:
VALUE_conv_float(P1);
VALUE_conv_float(P2);
P1->_float.value -= P2->_float.value; goto __END;
__POINTER:
VALUE_conv(P1, T_POINTER);
VALUE_conv(P2, T_POINTER);
P1->_pointer.value -= (intptr_t)P2->_pointer.value; goto __END;
__OBJECT_FLOAT:
operator_object_float(P1, P2, CO_SUBF);
goto __END;
__FLOAT_OBJECT:
operator_float_object(P1, P2, CO_SUBF);
goto __END;
__OBJECT_CONV:
operator_object_conv(P1, P2, CO_SUB);
goto __END;
__CONV_OBJECT:
operator_conv_object(P1, P2, CO_SUB);
goto __END;
__OBJECT:
operator_object(P1, P2, CO_SUB);
goto __END;
__VARIANT:
MANAGE_VARIANT_POINTER_OBJECT(_SUBR_sub);
goto __ERROR;
__ERROR:
THROW(E_TYPE, "Number", TYPE_get_name(type));
__END:
SP--;
}
static void _SUBR_mul(ushort code)
{
static void *jump[] = {
&&__VARIANT, &&__BOOLEAN, &&__BYTE, &&__SHORT, &&__INTEGER, &&__LONG, &&__SINGLE, &&__FLOAT, &&__ERROR,
&&__OBJECT_FLOAT, &&__FLOAT_OBJECT, &&__OBJECT_CONV, &&__CONV_OBJECT, &&__OBJECT
};
TYPE type;
VALUE *P1, *P2;
P1 = SP - 2;
P2 = P1 + 1;
type = code & 0x0F;
goto *jump[type];
__BOOLEAN:
P1->type = T_BOOLEAN;
P1->_integer.value = P1->_integer.value & P2->_integer.value; goto __END;
__BYTE:
P1->type = T_BYTE;
P1->_integer.value = (unsigned char)(P1->_integer.value * P2->_integer.value); goto __END;
__SHORT:
P1->type = T_SHORT;
P1->_integer.value = (short)(P1->_integer.value * P2->_integer.value); goto __END;
__INTEGER:
P1->type = T_INTEGER;
P1->_integer.value *= P2->_integer.value; goto __END;
__LONG:
VALUE_conv(P1, T_LONG);
VALUE_conv(P2, T_LONG);
P1->_long.value *= P2->_long.value; goto __END;
__SINGLE:
VALUE_conv(P1, T_SINGLE);
VALUE_conv(P2, T_SINGLE);
P1->_single.value *= P2->_single.value; goto __END;
__FLOAT:
VALUE_conv_float(P1);
VALUE_conv_float(P2);
P1->_float.value *= P2->_float.value;
//fprintf(stderr, "*: %.24g\n", P1->_float.value);
goto __END;
__OBJECT_FLOAT:
operator_object_float(P1, P2, CO_MULF);
goto __END;
__FLOAT_OBJECT:
operator_float_object(P1, P2, CO_MULF);
goto __END;
__OBJECT_CONV:
operator_object_conv(P1, P2, CO_MUL);
goto __END;
__CONV_OBJECT:
operator_conv_object(P1, P2, CO_MUL);
goto __END;
__OBJECT:
operator_object(P1, P2, CO_MUL);
goto __END;
__VARIANT:
MANAGE_VARIANT_OBJECT(_SUBR_mul);
goto __ERROR;
__ERROR:
THROW(E_TYPE, "Number", TYPE_get_name(type));
__END:
SP--;
}
static void _SUBR_div(ushort code)
{
static void *jump[] = {
&&__VARIANT, &&__BOOLEAN, &&__BYTE, &&__SHORT, &&__INTEGER, &&__LONG, &&__SINGLE, &&__FLOAT, &&__ERROR,
&&__OBJECT_FLOAT, &&__FLOAT_OBJECT, &&__OBJECT_CONV, &&__CONV_OBJECT, &&__OBJECT
};
TYPE type;
VALUE *P1, *P2;
P1 = SP - 2;
P2 = P1 + 1;
type = code & 0x0F;
goto *jump[type];
__BOOLEAN:
__BYTE:
__SHORT:
__INTEGER:
__LONG:
__SINGLE:
__FLOAT:
VALUE_conv_float(P1);
VALUE_conv_float(P2);
P1->_float.value /= P2->_float.value;
if (isfinite(P1->_float.value))
goto __END;
THROW(E_ZERO);
__OBJECT_FLOAT:
operator_object_float(P1, P2, CO_DIVF);
goto __CHECK_OBJECT;
__FLOAT_OBJECT:
operator_float_object(P1, P2, CO_IDIVF);
goto __CHECK_OBJECT;
__OBJECT_CONV:
operator_object_conv(P1, P2, CO_DIV);
goto __CHECK_OBJECT;
__CONV_OBJECT:
operator_conv_object(P1, P2, CO_DIV);
goto __CHECK_OBJECT;
__OBJECT:
operator_object(P1, P2, CO_DIV);
goto __CHECK_OBJECT;
__VARIANT:
MANAGE_VARIANT_OBJECT(_SUBR_div);
goto __ERROR;
__ERROR:
THROW(E_TYPE, "Number", TYPE_get_name(type));
__CHECK_OBJECT:
if (P1->_object.object == NULL)
THROW(E_ZERO);
__END:
SP--;
}
static void _SUBR_compi(ushort code)
{
static void *jump[17] = {
&&__VARIANT, &&__BOOLEAN, &&__BYTE, &&__SHORT, &&__INTEGER, &&__LONG, &&__SINGLE, &&__FLOAT, &&__DATE,
&&__STRING, &&__STRING, &&__POINTER, &&__ERROR, &&__ERROR, &&__ERROR, &&__NULL, &&__OBJECT
};
static void *test[] = { &&__GT, &&__LE, &&__LT, &&__GE };
char NO_WARNING(result);
VALUE *P1;
VALUE *P2;
TYPE type;
P1 = SP - 2;
P2 = P1 + 1;
type = code & 0x1F;
goto *jump[type];
__BOOLEAN:
__BYTE:
__SHORT:
__INTEGER:
result = P1->_integer.value > P2->_integer.value ? 1 : P1->_integer.value < P2->_integer.value ? -1 : 0;
goto __END;
__LONG:
VALUE_conv(P1, T_LONG);
VALUE_conv(P2, T_LONG);
result = P1->_long.value > P2->_long.value ? 1 : P1->_long.value < P2->_long.value ? -1 : 0;
goto __END;
__DATE:
VALUE_conv(P1, T_DATE);
VALUE_conv(P2, T_DATE);
result = DATE_comp_value(P1, P2);
goto __END;
__NULL:
__STRING:
VALUE_conv_string(P1);
VALUE_conv_string(P2);
result = STRING_compare(P1->_string.addr + P1->_string.start, P1->_string.len, P2->_string.addr + P2->_string.start, P2->_string.len);
RELEASE_STRING(P1);
RELEASE_STRING(P2);
goto __END;
__SINGLE:
VALUE_conv(P1, T_SINGLE);
VALUE_conv(P2, T_SINGLE);
result = P1->_single.value > P2->_single.value ? 1 : P1->_single.value < P2->_single.value ? -1 : 0;
goto __END;
__FLOAT:
VALUE_conv_float(P1);
VALUE_conv_float(P2);
result = P1->_float.value > P2->_float.value ? 1 : P1->_float.value < P2->_float.value ? -1 : 0;
goto __END;
__POINTER:
VALUE_conv(P1, T_POINTER);
VALUE_conv(P2, T_POINTER);
result = P1->_pointer.value > P2->_pointer.value ? 1 : P1->_pointer.value < P2->_pointer.value ? -1 : 0;
goto __END;
__OBJECT:
result = OBJECT_comp_value(P1, P2);
//RELEASE_OBJECT(P1);
//RELEASE_OBJECT(P2);
goto __END_RELEASE;
__VARIANT:
{
bool variant = FALSE;
if (TYPE_is_variant(P1->type))
{
VARIANT_undo(P1);
variant = TRUE;
}
if (TYPE_is_variant(P2->type))
{
VARIANT_undo(P2);
variant = TRUE;
}
type = Max(P1->type, P2->type);
if (type == T_NULL || TYPE_is_string(type))
{
TYPE typem = Min(P1->type, P2->type);
if (!TYPE_is_string(typem))
THROW(E_TYPE, TYPE_get_name(typem), TYPE_get_name(type));
}
else if (TYPE_is_object(type))
goto __ERROR;
else if (TYPE_is_void(type))
THROW(E_NRETURN);
if (!variant)
*PC |= type;
goto *jump[type];
}
__ERROR:
THROW(E_TYPE, "Number, Date or String", TYPE_get_name(type));
__END_RELEASE:
RELEASE(P1);
RELEASE(P2);
__END:
P1->type = T_BOOLEAN;
SP--;
goto *test[(code >> 8) - (C_GT >> 8)];
__GT:
P1->_boolean.value = result > 0 ? -1 : 0;
return;
__GE:
P1->_boolean.value = result >= 0 ? -1 : 0;
return;
__LT:
P1->_boolean.value = result < 0 ? -1 : 0;
return;
__LE:
P1->_boolean.value = result <= 0 ? -1 : 0;
return;
}

View File

@ -53,7 +53,7 @@ typedef
#define OBJECT_is(_object, _class) (OBJECT_class(_object) == _class)
#define OBJECT_is_class(_object) OBJECT_is(_object, CLASS_Class)
#define OBJECT_class(_object) ((_object) ? ((OBJECT *)_object)->class : NULL)
#define OBJECT_count(_object) ((_object) ? ((OBJECT *)_object)->ref : 0)
#define OBJECT_count(_object) (((OBJECT *)_object)->ref)
void *OBJECT_new(CLASS *class, const char *name, OBJECT *parent);
void OBJECT_attach(OBJECT *ob, OBJECT *parent, const char *name);

View File

@ -52,6 +52,30 @@
#include "gbx_subr_math_temp.h"
static bool check_operators(VALUE *P1)
{
return (TYPE_is_object(P1->type) && OBJECT_class(P1->_object.object)->has_operators);
}
static void operator_object_abs(VALUE *P1)
{
double (*func)(void *) = (double (*)(void *))((void **)(OBJECT_class(P1->_object.object)->operators))[CO_ABS];
double result = (*func)(P1->_object.object);
OBJECT_UNREF(P1->_object.object, "operator_object_abs");
P1->type = T_FLOAT;
P1->_float.value = result;
}
static void operator_object(VALUE *P1, uchar op)
{
void *(*func)(void *) = (void *(*)(void *))((void **)(OBJECT_class(P1->_object.object)->operators))[op];
void *result = (*func)(P1->_object.object);
OBJECT_REF(result, "operator_object");
OBJECT_UNREF(P1->_object.object, "operator_object");
P1->_object.object = result;
}
void SUBR_pi(ushort code)
{
SUBR_ENTER();
@ -135,7 +159,6 @@ 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,
@ -493,6 +516,41 @@ __END:
} \
})
#define MANAGE_VARIANT_OBJECT(_func) \
({ \
type = P1->type; \
\
if (TYPE_is_number_date(type)) \
{ \
*PC |= type; \
goto *jump[type]; \
} \
\
if (check_operators(P1)) \
{ \
*PC |= T_DATE + 1; \
goto *jump[T_DATE + 1]; \
} \
\
if (TYPE_is_variant(type)) \
{ \
VARIANT_undo(P1); \
type = P1->type; \
if (TYPE_is_number_date(type)) \
{ \
(_func)(code | type); \
VALUE_conv_variant(P1); \
return; \
} \
if (check_operators(P1)) \
{ \
(_func)(T_DATE + 1); \
VALUE_conv_variant(P1); \
return; \
} \
} \
})
void SUBR_sgn(ushort code)
{
@ -550,7 +608,7 @@ __END:
void SUBR_neg(ushort code)
{
static void *jump[] = {
&&__VARIANT, &&__BOOLEAN, &&__BYTE, &&__SHORT, &&__INTEGER, &&__LONG, &&__SINGLE, &&__FLOAT, &&__ERROR
&&__VARIANT, &&__BOOLEAN, &&__BYTE, &&__SHORT, &&__INTEGER, &&__LONG, &&__SINGLE, &&__FLOAT, &&__ERROR, &&__OBJECT
};
VALUE *P1;
@ -590,9 +648,14 @@ __FLOAT:
P1->_float.value = (-P1->_float.value); return;
__OBJECT:
operator_object(P1, CO_NEG);
return;
__VARIANT:
MANAGE_VARIANT(SUBR_neg);
MANAGE_VARIANT_OBJECT(SUBR_neg);
__ERROR:
@ -603,7 +666,7 @@ __ERROR:
void SUBR_abs(ushort code)
{
static void *jump[] = {
&&__VARIANT, &&__BOOLEAN, &&__BYTE, &&__SHORT, &&__INTEGER, &&__LONG, &&__SINGLE, &&__FLOAT, &&__ERROR
&&__VARIANT, &&__BOOLEAN, &&__BYTE, &&__SHORT, &&__INTEGER, &&__LONG, &&__SINGLE, &&__FLOAT, &&__ERROR, &&__OBJECT
};
VALUE *P1;
@ -643,9 +706,14 @@ __FLOAT:
P1->_float.value = fabs(P1->_float.value); return;
__OBJECT:
operator_object_abs(P1);
return;
__VARIANT:
MANAGE_VARIANT(SUBR_abs);
MANAGE_VARIANT_OBJECT(SUBR_abs);
__ERROR:

View File

@ -728,7 +728,13 @@ __OBJECT:
if (type == T_VARIANT)
goto __2v;
goto __N;
if (value->type == T_OBJECT)
class = OBJECT_class(value->_object.object);
else
class = value->_object.class;
goto __CONVERT;
//goto __N;
}
if (!TYPE_is_object(value->type))
@ -771,13 +777,7 @@ __OBJECT:
goto __TYPE;
if (value->type == T_OBJECT)
{
/*if (value->_object.object == NULL)
goto __TYPE;*/
class = OBJECT_class(value->_object.object);
/* on continue */
}
else
class = value->_object.class;
@ -799,14 +799,14 @@ __RETRY:
goto __RETRY;
}
if (class->special[SPEC_CONVERT] != NO_SYMBOL)
__CONVERT:
if (class->has_convert)
{
void *conv = ((void *(*)())(CLASS_get_desc(class, class->special[SPEC_CONVERT])->constant.value._pointer))(value->_object.object, type);
if (conv)
void *unref = value->_object.object;
if (!((bool (*)())(CLASS_get_desc(class, class->special[SPEC_CONVERT])->constant.value._pointer))(value->_object.object, type, value))
{
OBJECT_REF(conv, "VALUE_conv");
OBJECT_UNREF(value->_object.object, "VALUE_conv");
value->_object.object = conv;
OBJECT_UNREF(unref, "VALUE_conv");
goto __TYPE;
}
}
@ -1175,12 +1175,29 @@ __STRING:
__OBJECT:
if (VALUE_is_null(value))
goto __NULL;
{
CLASS *class;
if (VALUE_is_null(value))
goto __NULL;
*len = sprintf(COMMON_buffer, "(%s %p)", OBJECT_class(value->_object.object)->name, value->_object.object);
*addr = COMMON_buffer;
return;
class = OBJECT_class(value->_object.object);
if (class->has_convert)
{
VALUE temp;
if (!((bool (*)())(CLASS_get_desc(class, class->special[SPEC_CONVERT])->constant.value._pointer))(value->_object.object, T_CSTRING, &temp))
{
*addr = temp._string.addr + temp._string.start;
*len = temp._string.len;
STRING_free_later(*addr);
return;
}
}
*len = sprintf(COMMON_buffer, "(%s %p)", class->name, value->_object.object);
*addr = COMMON_buffer;
return;
}
__POINTER:

View File

@ -297,6 +297,7 @@ typedef
GB_BOOLEAN _boolean;
GB_INTEGER _integer;
GB_LONG _long;
GB_SINGLE _single;
GB_FLOAT _float;
GB_DATE _date;
GB_STRING _string;
@ -314,6 +315,7 @@ typedef
#define GB_ERR_NPROPERTY ((char *)17)
#define GB_ERR_ARG ((char *)20)
#define GB_ERR_BOUND ((char *)21)
#define GB_ERR_ZERO ((char *)26)
/* Gambas description start macro */
@ -813,6 +815,34 @@ typedef
#define POINTER(_pointer) (void **)(void *)_pointer
/* For classes that implements arithmetic operators (e.g. complex numbers...) */
typedef
struct {
int (*equal)(void *, void *);
int (*equalf)(void *, double);
int (*comp)(void *, void *);
int (*compf)(void *, double);
void *(*add)(void *, void *);
void *(*addf)(void *, double);
void *(*sub)(void *, void *);
void *(*subf)(void *, double);
void *(*mul)(void *, void *);
void *(*mulf)(void *, double);
void *(*div)(void *, void *);
void *(*divf)(void *, double);
void *(*idivf)(void *, double);
void *(*neg)(void *);
void *(*pow)(void *, void *);
void *(*powf)(void *, double);
void *(*abs)(void *);
void *(*max)(void *, void *);
void *(*min)(void *, void *);
}
PACKED
GB_OPERATOR_DESC;
/* Gambas Application Programming Interface */
typedef

View File

@ -26,6 +26,87 @@
#define STATIC_SUBR static
#endif
#define OP_OBJECT_FLOAT (T_POINTER + 1)
#define OP_FLOAT_OBJECT (T_POINTER + 2)
#define OP_OBJECT_CONV (T_POINTER + 3)
#define OP_CONV_OBJECT (T_POINTER + 4)
#define OP_OBJECT (T_POINTER + 5)
static int check_operators(VALUE *P1, VALUE *P2)
{
if (TYPE_is_number(P1->type))
{
if (OBJECT_class(P2->_object.object)->operators)
return OP_FLOAT_OBJECT;
}
else if (TYPE_is_number(P2->type))
{
if (OBJECT_class(P1->_object.object)->operators)
return OP_OBJECT_FLOAT;
}
else
{
CLASS *class1 = OBJECT_class(P1->_object.object);
CLASS *class2 = OBJECT_class(P2->_object.object);
if (class1->operators)
{
if (class1 == class2)
return OP_OBJECT;
if (class2->operators)
{
if (class1->operators->strength > class2->operators->strength)
return OP_OBJECT_CONV;
else
return OP_CONV_OBJECT;
}
}
}
return 0;
}
static void operator_object_float(VALUE *P1, VALUE *P2, uchar op)
{
void *(*func)(void *, double) = (void *(*)(void *, double))((void **)(OBJECT_class(P1->_object.object)->operators))[op];
VALUE_conv_float(P2);
void *result = (*func)(P1->_object.object, P2->_float.value);
OBJECT_unref(P1->_object.object);
P1->_object.object = result;
}
static void operator_float_object(VALUE *P1, VALUE *P2, uchar op)
{
void *(*func)(void *, double) = (void *(*)(void *, double))((void **)(OBJECT_class(P2->_object.object)->operators))[op];
VALUE_conv_float(P1);
void *result = (*func)(P2->_object.object, P1->_float.value);
P1->_object.class = P2->_object.class;
OBJECT_unref(P2->_object.object);
P1->_object.object = result;
}
static void operator_object(VALUE *P1, VALUE *P2, uchar op)
{
void *(*func)(void *, void *) = (void *(*)(void *, void *))((void **)(OBJECT_class(P2->_object.object)->operators))[op];
void *result = (*func)(P1->_object.object, P2->_object.object);
OBJECT_unref(P1->_object.object);
OBJECT_unref(P2->_object.object);
P1->_object.object = result;
}
static void operator_object_conv(VALUE *P1, VALUE *P2, char op)
{
VALUE_conv(P2, (TYPE)P1->_object.class);
operator_object(P1, P2, op);
}
static void operator_conv_object(VALUE *P1, VALUE *P2, char op)
{
VALUE_conv(P1, (TYPE)P2->_object.class);
operator_object(P1, P2, op);
}
#define MANAGE_VARIANT(_func) \
({ \
type = Max(P1->type, P2->type); \
@ -95,10 +176,57 @@
})
#define MANAGE_VARIANT_POINTER_OBJECT(_func) \
({ \
type = Max(P1->type, P2->type); \
if (TYPE_is_void(P1->type) || TYPE_is_void(P2->type)) \
THROW(E_NRETURN); \
\
if (TYPE_is_number_date(type) || TYPE_is_pointer(type)) \
{ \
*PC |= type; \
goto *jump[type]; \
} \
\
VARIANT_undo(P1); \
VARIANT_undo(P2); \
\
if (TYPE_is_string(P1->type)) \
VALUE_conv_float(P1); \
\
if (TYPE_is_string(P2->type)) \
VALUE_conv_float(P2); \
\
if (TYPE_is_null(P1->type) || TYPE_is_null(P2->type)) \
type = T_NULL; \
else \
type = Max(P1->type, P2->type); \
\
if (TYPE_is_number_date(type) || TYPE_is_pointer(type)) \
{ \
(_func)(code | type); \
VALUE_conv_variant(P1); \
return; \
} \
\
if (TYPE_is_object(type)) \
{ \
type = check_operators(P1, P2); \
if (type) \
{ \
*PC |= type; \
goto *jump[type]; \
} \
} \
})
STATIC_SUBR void _SUBR_add(ushort code)
{
static void *jump[] = {
&&__VARIANT, &&__BOOLEAN, &&__BYTE, &&__SHORT, &&__INTEGER, &&__LONG, &&__SINGLE, &&__FLOAT, &&__DATE, NULL, NULL, &&__POINTER
&&__VARIANT, &&__BOOLEAN, &&__BYTE, &&__SHORT, &&__INTEGER, &&__LONG, &&__SINGLE, &&__FLOAT,
&&__DATE, NULL, NULL, &&__POINTER,
&&__OBJECT_FLOAT, &&__FLOAT_OBJECT, &&__OBJECT_CONV, &&__CONV_OBJECT, &&__OBJECT
};
TYPE type;
@ -161,11 +289,36 @@ __POINTER:
P1->_pointer.value += (intptr_t)P2->_pointer.value; goto __END;
__OBJECT_FLOAT:
operator_object_float(P1, P2, CO_ADDF);
goto __END;
__FLOAT_OBJECT:
operator_float_object(P1, P2, CO_ADDF);
goto __END;
__OBJECT_CONV:
operator_object_conv(P1, P2, CO_ADDF);
goto __END;
__CONV_OBJECT:
operator_conv_object(P1, P2, CO_ADDF);
goto __END;
__OBJECT:
operator_object(P1, P2, CO_ADDF);
goto __END;
__VARIANT:
MANAGE_VARIANT_POINTER(_SUBR_add);
MANAGE_VARIANT_POINTER_OBJECT(_SUBR_add);
goto __ERROR;
__ERROR:
THROW(E_TYPE, "Number", TYPE_get_name(type));