[INTERPRETER]

* NEW: Add a GB.FreeStringLater() API to allow components to create a new
  string with GB.NewString(), and let the interpreter frees it later.

[GB.GSL]
* NEW: Add a ToString() method to all classes. That method takes two 
  arguments: the first one tells if number must be localized. The second 
  one tells if complex numbers and polynomials are converted to a string
  that can be sent to Eval().
* BUG: Adding a number N to a Matrix A is equivalent to adding N times the
  identity matrix.
* NEW: The '^' operator has been implemented in the Matrix class. Only A^N
  where N is an integer is valid.


git-svn-id: svn://localhost/gambas/trunk@4955 867c0c6c-44f3-4631-809d-bfa615b0a4ec
This commit is contained in:
Benoît Minisini 2012-07-15 13:07:57 +00:00
parent f32d220bc1
commit 7c9f99fef6
9 changed files with 160 additions and 46 deletions

View file

@ -1,9 +1,9 @@
# Gambas Project File 3.0
# Compiled with Gambas 3.0.0
# Compiled with Gambas 3.2.0
Title=Gambas DBus Explorer
Startup=FVersiongbXML
Icon=dbus64.png
Version=3.0.0
Version=3.2.0
VersionFile=1
Component=gb.image
Component=gb.gui
@ -11,7 +11,8 @@ Component=gb.form
Component=gb.dbus
Component=gb.settings
Component=gb.form.mdi
Component=gb.xml
Component=gb.libxml
Authors="Fabien Bodard\nBenoît Minisini"
Environment="GB_GUI=gb.qt4"
TabSize=2
Packager=1

View file

@ -2,7 +2,7 @@ FVersiongbXML
Gambas DBus Explorer
0
0
3.0.0
3.2.0
gb.image
gb.gui
@ -10,5 +10,5 @@ gb.form
gb.dbus
gb.settings
gb.form.mdi
gb.xml
gb.libxml

View file

@ -238,7 +238,7 @@ static GB_OPERATOR_DESC _operator =
//---- Conversions ----------------------------------------------------------
char *COMPLEX_to_string(gsl_complex number, bool local)
char *COMPLEX_to_string(gsl_complex number, bool local, bool eval)
{
char buffer[64];
char *p;
@ -250,7 +250,7 @@ char *COMPLEX_to_string(gsl_complex number, bool local)
imag = number.dat[1];
if (real == 0.0 && imag == 0.0)
return GB.NewString("0", 1);
return GB.TempString("0", 1);
p = buffer;
@ -271,7 +271,7 @@ char *COMPLEX_to_string(gsl_complex number, bool local)
else if (p != buffer)
*p++ = '+';
if (imag != 1.0)
if (imag != 1.0 || eval)
{
GB.NumberToString(local, imag, NULL, &str, &len);
strncpy(p, str, len);
@ -309,7 +309,7 @@ static bool _convert(CCOMPLEX *a, GB_TYPE type, GB_VALUE *conv)
case GB_T_STRING:
case GB_T_CSTRING:
conv->_string.value.addr = COMPLEX_to_string(a->number, type == GB_T_CSTRING);
conv->_string.value.addr = COMPLEX_to_string(a->number, type == GB_T_CSTRING, FALSE);
conv->_string.value.start = 0;
conv->_string.value.len = GB.StringLength(conv->_string.value.addr);
return FALSE;
@ -366,6 +366,13 @@ BEGIN_METHOD_VOID(Complex_Copy)
END_METHOD
BEGIN_METHOD(Complex_ToString, GB_BOOLEAN local; GB_BOOLEAN eval)
GB.ReturnString(GB.FreeStringLater(COMPLEX_to_string(THIS->number, VARGOPT(local, FALSE), VARGOPT(eval, FALSE))));
END_METHOD
BEGIN_METHOD(Complex_Polar, GB_FLOAT real; GB_FLOAT imag)
GB.ReturnObject(COMPLEX_create(gsl_complex_polar(VARG(real), VARG(imag))));
@ -579,6 +586,7 @@ GB_DESC ComplexDesc[] =
GB_STATIC_METHOD("Polar", "Complex", Complex_Polar, "[(Abs)f(Arg)f]"),
GB_METHOD("Copy", "Complex", Complex_Copy, NULL),
GB_METHOD("ToString", "s", Complex_ToString, "[(Local)b(ForEval)b]"),
GB_METHOD("Conj", "Complex", Complex_Conjugate, NULL),
GB_METHOD("Neg", "Complex", Complex_Negative, NULL),

View file

@ -60,7 +60,7 @@ enum
CCOMPLEX *COMPLEX_create(gsl_complex number);
CCOMPLEX *COMPLEX_push_complex(double value);
char *COMPLEX_to_string(gsl_complex number, bool local);
char *COMPLEX_to_string(gsl_complex number, bool local, bool eval);
#define COMPLEX_get(_c) ((_c) ? (_c)->number : COMPLEX_zero)

View file

@ -51,6 +51,18 @@ static CMATRIX *MATRIX_create(int width, int height, bool complex, bool init)
return m;
}
static CMATRIX *MATRIX_identity(int width, int height, bool complex)
{
CMATRIX *m = MATRIX_create(width, height, complex, FALSE);
if (complex)
gsl_matrix_complex_set_identity(CMAT(m));
else
gsl_matrix_set_identity(MAT(m));
return m;
}
static CMATRIX *MATRIX_create_from(void *matrix, bool complex)
{
CMATRIX *m = GB.Create(CLASS_Matrix, NULL,NULL);
@ -151,7 +163,7 @@ static void matrix_negative(void *m, bool complex)
d[i] = -d[i];
}
static bool get_determinant(CMATRIX *m, COMPLEX_VALUE *det)
static bool matrix_determinant(CMATRIX *m, COMPLEX_VALUE *det)
{
int sign = 0;
int size = WIDTH(m);
@ -225,6 +237,26 @@ static void *matrix_invert(void *m, bool complex)
return result;
}
static void matrix_add_identity(gsl_matrix *m, double f)
{
gsl_matrix *id = gsl_matrix_alloc(m->size1, m->size2);
gsl_matrix_set_identity(id);
gsl_matrix_scale(id, f);
gsl_matrix_add(m, id);
gsl_matrix_free(id);
}
static void matrix_complex_add_identity(gsl_matrix_complex *m, gsl_complex c)
{
gsl_matrix_complex *id = gsl_matrix_complex_alloc(m->size1, m->size2);
gsl_matrix_complex_set_identity(id);
gsl_matrix_complex_scale(id, c);
gsl_matrix_complex_add(m, id);
gsl_matrix_complex_free(id);
}
//---- Arithmetic operators -------------------------------------------------
#define IMPLEMENT_OP(_name) \
@ -288,13 +320,13 @@ IMPLEMENT_OP(_add)
#undef FUNC
#undef CFUNC
#define FUNC(_m, _a, _f) gsl_matrix_add_constant(_m, _f)
#define CFUNC(_m, _a, _f) gsl_matrix_complex_add_constant(_m, gsl_complex_rect(_f, 0))
#define FUNC(_m, _a, _f) matrix_add_identity(_m, _f)
#define CFUNC(_m, _a, _f) matrix_complex_add_identity(_m, gsl_complex_rect(_f, 0))
IMPLEMENT_OP_FLOAT(_addf)
#undef FUNC
#undef CFUNC
#define CFUNC(_m, _a, _c) gsl_matrix_complex_add_constant(_m, _c)
#define CFUNC(_m, _a, _c) matrix_complex_add_identity(_m, _c)
IMPLEMENT_OP_OTHER(_addo)
#undef CFUNC
@ -308,19 +340,19 @@ IMPLEMENT_OP(_sub)
if (invert) \
{ \
matrix_negative(_m, FALSE); \
gsl_matrix_add_constant(_m, _f); \
matrix_add_identity(_m, _f); \
} \
else \
gsl_matrix_add_constant(_m, -(_f));
matrix_add_identity(_m, -(_f));
#define CFUNC(_m, _a, _f) \
if (invert) \
{ \
matrix_negative(_m, TRUE); \
gsl_matrix_complex_add_constant(_m, gsl_complex_rect((_f), 0)); \
matrix_complex_add_identity(_m, gsl_complex_rect(_f, 0)); \
} \
else \
gsl_matrix_complex_add_constant(_m, gsl_complex_rect(-(_f), 0));
matrix_complex_add_identity(_m, gsl_complex_rect(-(_f), 0));
IMPLEMENT_OP_FLOAT(_subf)
#undef FUNC
@ -331,7 +363,7 @@ IMPLEMENT_OP_FLOAT(_subf)
matrix_negative(_m, TRUE); \
else \
gsl_complex_negative(_c); \
gsl_matrix_complex_add_constant(_m, _c);
matrix_complex_add_identity(_m, _c);
IMPLEMENT_OP_OTHER(_subo)
#undef CFUNC
@ -477,6 +509,65 @@ static CMATRIX *_neg(CMATRIX *a)
return m;
}
static CMATRIX *_powf(CMATRIX *a, double f, bool invert)
{
if (invert || f != (double)(int)f)
return NULL;
CMATRIX *m;
int i;
int n = (int)f;
if (n == 0)
{
m = MATRIX_make(a);
if (COMPLEX(m))
gsl_matrix_complex_set_identity(CMAT(m));
else
gsl_matrix_set_identity(MAT(m));
}
else if (n == 1)
{
m = a;
}
else if (n > 0)
{
CMATRIX *m2;
m = MATRIX_copy(a);
for (i = 1; i < n; i++)
{
m2 = _mul(m, a, FALSE);
GB.Unref(POINTER(&m));
m = m2;
}
}
else if (n < 0)
{
void *inv = matrix_invert(a->matrix, COMPLEX(a));
if (inv == NULL)
{
GB.Error(GB_ERR_ZERO);
return NULL;
}
m = MATRIX_make(a);
if (COMPLEX(m))
gsl_matrix_complex_memcpy(CMAT(m), inv);
else
gsl_matrix_memcpy(MAT(m), inv);
a = MATRIX_create_from(inv, COMPLEX(a));
for (i = 1; i < (-n); i++)
m = _mul(m, a, FALSE);
GB.Unref(POINTER(&a));
}
return m;
}
static GB_OPERATOR_DESC _operator =
{
.equal = (void *)_equal,
@ -493,12 +584,13 @@ static GB_OPERATOR_DESC _operator =
.div = (void *)_div,
.divf = (void *)_divf,
.divo = (void *)_divo,
.powf = (void *)_powf,
.neg = (void *)_neg
};
//---- Conversions ----------------------------------------------------------
static char *_to_string(CMATRIX *_object, bool local)
static char *_to_string(CMATRIX *_object, bool local, bool eval)
{
char *result = NULL;
int i, j;
@ -525,7 +617,7 @@ static char *_to_string(CMATRIX *_object, bool local)
}
else
{
str = COMPLEX_to_string(gsl_matrix_complex_get(CMAT(THIS), i, j), local);
str = COMPLEX_to_string(gsl_matrix_complex_get(CMAT(THIS), i, j), local, eval);
result = GB.AddString(result, str, GB.StringLength(str));
GB.FreeString(&str);
}
@ -567,7 +659,7 @@ static bool _convert(CMATRIX *_object, GB_TYPE type, GB_VALUE *conv)
case GB_T_STRING:
case GB_T_CSTRING:
conv->_string.value.addr = _to_string(THIS, type == GB_T_CSTRING);
conv->_string.value.addr = _to_string(THIS, type == GB_T_CSTRING, FALSE);
conv->_string.value.start = 0;
conv->_string.value.len = GB.StringLength(conv->_string.value.addr);
return FALSE;
@ -600,7 +692,7 @@ static bool _convert(CMATRIX *_object, GB_TYPE type, GB_VALUE *conv)
case GB_T_STRING:
case GB_T_CSTRING:
conv->_string.value.addr = _to_string(THIS, type == GB_T_CSTRING);
conv->_string.value.addr = _to_string(THIS, type == GB_T_CSTRING, FALSE);
conv->_string.value.start = 0;
conv->_string.value.len = GB.StringLength(conv->_string.value.addr);
return FALSE;
@ -933,14 +1025,7 @@ END_PROPERTY
BEGIN_METHOD(Matrix_Identity, GB_INTEGER width; GB_INTEGER height; GB_BOOLEAN complex)
CMATRIX *m = MATRIX_create(VARGOPT(width, 2), VARGOPT(height, 2), VARGOPT(complex, FALSE), FALSE);
if (COMPLEX(m))
gsl_matrix_complex_set_identity(CMAT(m));
else
gsl_matrix_set_identity(MAT(m));
GB.ReturnObject(m);
GB.ReturnObject(MATRIX_identity(VARGOPT(width, 2), VARGOPT(height, 2), VARGOPT(complex, FALSE)));
END_METHOD
@ -1073,7 +1158,7 @@ BEGIN_METHOD_VOID(Matrix_Determinant)
COMPLEX_VALUE cv;
if (get_determinant(THIS, &cv))
if (matrix_determinant(THIS, &cv))
{
GB.Error("Matrix is not square");
return;
@ -1145,6 +1230,14 @@ BEGIN_METHOD_VOID(Matrix_Invert)
END_METHOD
BEGIN_METHOD(Matrix_ToString, GB_BOOLEAN local; GB_BOOLEAN eval)
GB.ReturnString(GB.FreeStringLater(_to_string(THIS, VARGOPT(local, FALSE), VARGOPT(eval, FALSE))));
END_METHOD
//---------------------------------------------------------------------------
GB_DESC MatrixDesc[] =
@ -1155,6 +1248,7 @@ GB_DESC MatrixDesc[] =
GB_METHOD("_free", NULL, Matrix_free, NULL),
//GB_STATIC_METHOD("_call", "Vector", Matrix_call, "(Value)f."),
GB_METHOD("Copy", "Matrix", Matrix_Copy, NULL),
GB_METHOD("ToString", "s", Matrix_ToString, "[(Local)b(ForEval)b]"),
GB_STATIC_METHOD("Identity", "Matrix", Matrix_Identity, "[(Width)i(Height)i(Complex)b]"),

View file

@ -391,7 +391,7 @@ static GB_OPERATOR_DESC _operator =
//---- Conversions ----------------------------------------------------------
char *POLYNOMIAL_to_string(CPOLYNOMIAL *p, bool local)
char *POLYNOMIAL_to_string(CPOLYNOMIAL *p, bool local, bool eval)
{
int i;
int size = COUNT(p);
@ -404,7 +404,6 @@ char *POLYNOMIAL_to_string(CPOLYNOMIAL *p, bool local)
bool complex = COMPLEX(p);
gsl_complex c;
bool par;
int l;
i = size;
while (i > 0)
@ -433,7 +432,7 @@ char *POLYNOMIAL_to_string(CPOLYNOMIAL *p, bool local)
else if (re > 0.0 || (re == 0.0 && im > 0.0) || par)
result = GB.AddChar(result, '+');
l = GB.StringLength(result);
//l = GB.StringLength(result);
if (par)
result = GB.AddChar(result, '(');
@ -455,9 +454,9 @@ char *POLYNOMIAL_to_string(CPOLYNOMIAL *p, bool local)
if (re != 0.0 && im > 0.0)
result = GB.AddChar(result, '+');
if (im == -1.0)
if (!eval && im == -1.0)
result = GB.AddChar(result, '-');
else if (im != 1.0)
else if (eval || im != 1.0)
{
GB.NumberToString(local, im, NULL, &str, &len);
result = GB.AddString(result, str, len);
@ -471,7 +470,7 @@ char *POLYNOMIAL_to_string(CPOLYNOMIAL *p, bool local)
if (i > 0)
{
if (GB.StringLength(result) > l)
if (eval && ((im == 0 && re != 0 && re != 1 && re != -1) || (im != 0)))
result = GB.AddChar(result, '*');
result = GB.AddChar(result, 'x');
if (i > 1)
@ -497,7 +496,7 @@ bool POLYNOMIAL_convert(CPOLYNOMIAL *a, GB_TYPE type, GB_VALUE *conv)
{
case GB_T_STRING:
case GB_T_CSTRING:
conv->_string.value.addr = POLYNOMIAL_to_string(a, type == GB_T_CSTRING);
conv->_string.value.addr = POLYNOMIAL_to_string(a, type == GB_T_CSTRING, FALSE);
conv->_string.value.start = 0;
conv->_string.value.len = GB.StringLength(conv->_string.value.addr);
return FALSE;
@ -629,9 +628,9 @@ BEGIN_PROPERTY(Polynomial_Degree)
END_PROPERTY
BEGIN_METHOD_VOID(Polynomial_ToString)
BEGIN_METHOD(Polynomial_ToString, GB_BOOLEAN local; GB_BOOLEAN eval)
GB.ReturnString(POLYNOMIAL_to_string(THIS, FALSE));
GB.ReturnString(GB.FreeStringLater(POLYNOMIAL_to_string(THIS, VARGOPT(local, FALSE), VARGOPT(eval, FALSE))));
END_METHOD
@ -897,7 +896,7 @@ GB_DESC PolynomialDesc[] =
GB_METHOD("_new", NULL, Polynomial_new, "[(Size)i(Complex)b]"),
GB_METHOD("_free", NULL, Polynomial_free, NULL),
GB_METHOD("ToString", "s", Polynomial_ToString, NULL),
GB_METHOD("ToString", "s", Polynomial_ToString, "[(Local)b(ForEval)b]"),
GB_PROPERTY_READ("Degree", "i", Polynomial_Degree),
GB_PROPERTY_READ("Count", "i", Polynomial_Count),

View file

@ -350,7 +350,7 @@ static GB_OPERATOR_DESC _operator =
//---- Conversions ----------------------------------------------------------
static char *_to_string(CVECTOR *_object, bool local)
static char *_to_string(CVECTOR *_object, bool local, bool eval)
{
char *result = NULL;
int i;
@ -372,7 +372,7 @@ static char *_to_string(CVECTOR *_object, bool local)
}
else
{
str = COMPLEX_to_string(gsl_vector_complex_get(CVEC(THIS), i), local);
str = COMPLEX_to_string(gsl_vector_complex_get(CVEC(THIS), i), local, eval);
result = GB.AddString(result, str, GB.StringLength(str));
GB.FreeString(&str);
}
@ -411,7 +411,7 @@ static bool _convert(CVECTOR *_object, GB_TYPE type, GB_VALUE *conv)
case GB_T_STRING:
case GB_T_CSTRING:
conv->_string.value.addr = _to_string(THIS, type == GB_T_CSTRING);
conv->_string.value.addr = _to_string(THIS, type == GB_T_CSTRING, FALSE);
conv->_string.value.start = 0;
conv->_string.value.len = GB.StringLength(conv->_string.value.addr);
return FALSE;
@ -444,7 +444,7 @@ static bool _convert(CVECTOR *_object, GB_TYPE type, GB_VALUE *conv)
case GB_T_STRING:
case GB_T_CSTRING:
conv->_string.value.addr = _to_string(THIS, type == GB_T_CSTRING);
conv->_string.value.addr = _to_string(THIS, type == GB_T_CSTRING, FALSE);
conv->_string.value.start = 0;
conv->_string.value.len = GB.StringLength(conv->_string.value.addr);
return FALSE;
@ -848,6 +848,15 @@ BEGIN_PROPERTY(Vector_Handle)
END_PROPERTY
BEGIN_METHOD(Vector_ToString, GB_BOOLEAN local; GB_BOOLEAN eval)
GB.ReturnString(GB.FreeStringLater(_to_string(THIS, VARGOPT(local, FALSE), VARGOPT(eval, FALSE))));
END_METHOD
//---------------------------------------------------------------------
GB_DESC VectorDesc[] =
{
GB_DECLARE("Vector", sizeof(CVECTOR)),
@ -856,6 +865,7 @@ GB_DESC VectorDesc[] =
GB_METHOD("_free", NULL, Vector_free, NULL),
//GB_STATIC_METHOD("_call", "Vector", Vector_call, "(Value)f."),
GB_METHOD("Copy", "Vector", Vector_Copy, NULL),
GB_METHOD("ToString", "s", Vector_ToString, "[(Local)b(ForEval)b]"),
GB_PROPERTY_READ("Count", "i", Vector_Count),
GB_PROPERTY_READ("Handle", "p", Vector_Handle),

View file

@ -164,6 +164,7 @@ const void *GAMBAS_Api[] =
(void *)GB_NewZeroString,
(void *)GB_TempString,
(void *)GB_FreeString,
(void *)STRING_free_later,
(void *)STRING_extend,
(void *)STRING_add,
(void *)STRING_add_char,

View file

@ -953,6 +953,7 @@ typedef
char *(*NewZeroString)(const char *);
char *(*TempString)(const char *, int);
void (*FreeString)(char **);
char *(*FreeStringLater)(char *);
char *(*ExtendString)(char *, int);
char *(*AddString)(char *, const char *, int);
char *(*AddChar)(char *, char);