2012-07-09 01:23:24 +02:00
|
|
|
/***************************************************************************
|
|
|
|
|
2012-07-13 01:34:14 +02:00
|
|
|
c_vector.c
|
2012-07-09 01:23:24 +02:00
|
|
|
|
|
|
|
gb.gsl component
|
|
|
|
|
|
|
|
(c) 2012 Benoît Minisini <gambas@users.sourceforge.net>
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
#define __C_MATRIX_C
|
|
|
|
|
2012-07-13 01:34:14 +02:00
|
|
|
#include "c_complex.h"
|
|
|
|
#include "c_vector.h"
|
2012-07-09 01:23:24 +02:00
|
|
|
#include "c_matrix.h"
|
|
|
|
|
2012-07-13 01:34:14 +02:00
|
|
|
#define THIS ((CMATRIX *)_object)
|
|
|
|
#define MAT(_m) ((gsl_matrix *)(_m)->matrix)
|
|
|
|
#define CMAT(_m) ((gsl_matrix_complex *)(_m)->matrix)
|
|
|
|
#define HEIGHT(_m) ((int)(MAT(_m)->size1))
|
|
|
|
#define WIDTH(_m) ((int)(MAT(_m)->size2))
|
|
|
|
#define COMPLEX(_m) ((_m)->complex)
|
2012-07-09 01:23:24 +02:00
|
|
|
|
|
|
|
//---- Matrix creation ------------------------------------------------------
|
|
|
|
|
2012-07-13 01:34:14 +02:00
|
|
|
static CMATRIX *MATRIX_create(int width, int height, bool complex)
|
2012-07-09 01:23:24 +02:00
|
|
|
{
|
2012-07-13 01:34:14 +02:00
|
|
|
GB.Push(3, GB_T_INTEGER, width, GB_T_INTEGER, height, GB_T_BOOLEAN, complex);
|
|
|
|
return (CMATRIX *)GB.New(CLASS_Matrix, NULL, (void *)(intptr_t)3);
|
2012-07-09 01:23:24 +02:00
|
|
|
}
|
|
|
|
|
2012-07-13 01:34:14 +02:00
|
|
|
static CMATRIX *MATRIX_copy(CMATRIX *_object)
|
2012-07-09 01:23:24 +02:00
|
|
|
{
|
2012-07-13 01:34:14 +02:00
|
|
|
CMATRIX *copy = MATRIX_create(WIDTH(THIS), HEIGHT(THIS), COMPLEX(THIS));
|
|
|
|
if (COMPLEX(THIS))
|
|
|
|
gsl_matrix_memcpy(MAT(copy), MAT(THIS));
|
|
|
|
else
|
|
|
|
gsl_matrix_complex_memcpy(CMAT(copy), CMAT(THIS));
|
|
|
|
|
2012-07-09 01:23:24 +02:00
|
|
|
return copy;
|
|
|
|
}
|
|
|
|
|
2012-07-13 01:34:14 +02:00
|
|
|
static CMATRIX *MATRIX_convert_to_complex(CMATRIX *_object)
|
2012-07-09 01:23:24 +02:00
|
|
|
{
|
2012-07-13 01:34:14 +02:00
|
|
|
CMATRIX *m = MATRIX_create(WIDTH(THIS), HEIGHT(THIS), TRUE);
|
|
|
|
int i, j;
|
2012-07-09 01:23:24 +02:00
|
|
|
|
2012-07-13 01:34:14 +02:00
|
|
|
for (i = 0; i < HEIGHT(THIS); i++)
|
|
|
|
for (j = 0; j < WIDTH(THIS); j++)
|
|
|
|
gsl_matrix_complex_set(CMAT(m), i, j, gsl_complex_rect(gsl_matrix_get(MAT(THIS), i, j), 0));
|
2012-07-09 01:23:24 +02:00
|
|
|
|
2012-07-13 01:34:14 +02:00
|
|
|
return m;
|
2012-07-09 01:23:24 +02:00
|
|
|
}
|
|
|
|
|
2012-07-13 01:34:14 +02:00
|
|
|
static void ensure_complex(CMATRIX *_object)
|
2012-07-09 01:23:24 +02:00
|
|
|
{
|
2012-07-13 01:34:14 +02:00
|
|
|
gsl_matrix_complex *v;
|
|
|
|
int w = WIDTH(THIS);
|
|
|
|
int h = HEIGHT(THIS);
|
|
|
|
int i, j;
|
2012-07-09 01:23:24 +02:00
|
|
|
|
2012-07-13 01:34:14 +02:00
|
|
|
if (COMPLEX(THIS))
|
|
|
|
return;
|
2012-07-09 01:23:24 +02:00
|
|
|
|
2012-07-13 01:34:14 +02:00
|
|
|
v = gsl_matrix_complex_alloc(h, w);
|
|
|
|
for (i = 0; i < h; i++)
|
|
|
|
for (j = 0; j < w; j++)
|
|
|
|
gsl_matrix_complex_set(v, i, j, gsl_complex_rect(gsl_matrix_get(MAT(THIS), i, j), 0));
|
2012-07-09 01:23:24 +02:00
|
|
|
|
2012-07-13 01:34:14 +02:00
|
|
|
gsl_matrix_free(MAT(THIS));
|
|
|
|
THIS->matrix = v;
|
|
|
|
THIS->complex = TRUE;
|
2012-07-09 01:23:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-07-13 01:34:14 +02:00
|
|
|
/*static bool ensure_not_complex(CMATRIX *_object)
|
2012-07-09 01:23:24 +02:00
|
|
|
{
|
2012-07-13 01:34:14 +02:00
|
|
|
gsl_matrix *v;
|
|
|
|
int size = SIZE(THIS);
|
2012-07-09 01:23:24 +02:00
|
|
|
int i;
|
2012-07-13 01:34:14 +02:00
|
|
|
gsl_complex c;
|
|
|
|
|
|
|
|
if (!COMPLEX(THIS))
|
|
|
|
return FALSE;
|
2012-07-09 01:23:24 +02:00
|
|
|
|
|
|
|
for (i = 0; i < size; i++)
|
|
|
|
{
|
2012-07-13 01:34:14 +02:00
|
|
|
c = gsl_matrix_complex_get(CMAT(THIS), i);
|
|
|
|
if (GSL_IMAG(c) != 0.0)
|
|
|
|
return TRUE;
|
2012-07-09 01:23:24 +02:00
|
|
|
}
|
|
|
|
|
2012-07-13 01:34:14 +02:00
|
|
|
v = gsl_matrix_alloc(size);
|
|
|
|
|
|
|
|
for (i = 0; i < size; i++)
|
|
|
|
gsl_matrix_set(v, i, GSL_REAL(gsl_matrix_complex_get(CMAT(THIS), i)));
|
|
|
|
|
|
|
|
gsl_matrix_complex_free(CMAT(THIS));
|
|
|
|
THIS->matrix = v;
|
|
|
|
THIS->complex = FALSE;
|
|
|
|
return FALSE;
|
|
|
|
}*/
|
2012-07-09 01:23:24 +02:00
|
|
|
|
|
|
|
//---- Conversions ----------------------------------------------------------
|
|
|
|
|
2012-07-13 01:34:14 +02:00
|
|
|
static char *_to_string(CMATRIX *_object, bool local)
|
2012-07-09 01:23:24 +02:00
|
|
|
{
|
|
|
|
char *result = NULL;
|
2012-07-13 01:34:14 +02:00
|
|
|
int i, j;
|
|
|
|
int w = WIDTH(THIS);
|
|
|
|
int h = HEIGHT(THIS);
|
2012-07-09 01:23:24 +02:00
|
|
|
char *str;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
result = GB.AddChar(result, '[');
|
|
|
|
|
2012-07-13 01:34:14 +02:00
|
|
|
for (i = 0; i < w; i++)
|
2012-07-09 01:23:24 +02:00
|
|
|
{
|
2012-07-13 01:34:14 +02:00
|
|
|
result = GB.AddChar(result, '[');
|
|
|
|
|
|
|
|
for (j = 0; j < h; j++)
|
|
|
|
{
|
|
|
|
if (j)
|
|
|
|
result = GB.AddChar(result, ' ');
|
|
|
|
|
|
|
|
if (!COMPLEX(THIS))
|
|
|
|
{
|
|
|
|
GB.NumberToString(local, gsl_matrix_get(MAT(THIS), i, j), NULL, &str, &len);
|
|
|
|
result = GB.AddString(result, str, len);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
str = COMPLEX_to_string(gsl_matrix_complex_get(CMAT(THIS), i, j), local);
|
|
|
|
result = GB.AddString(result, str, GB.StringLength(str));
|
|
|
|
GB.FreeString(&str);
|
|
|
|
}
|
|
|
|
}
|
2012-07-09 01:23:24 +02:00
|
|
|
|
2012-07-13 01:34:14 +02:00
|
|
|
result = GB.AddChar(result, ']');
|
2012-07-09 01:23:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
result = GB.AddChar(result, ']');
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2012-07-13 01:34:14 +02:00
|
|
|
static bool _convert(CMATRIX *_object, GB_TYPE type, GB_VALUE *conv)
|
2012-07-09 01:23:24 +02:00
|
|
|
{
|
2012-07-13 01:34:14 +02:00
|
|
|
if (THIS)
|
2012-07-09 01:23:24 +02:00
|
|
|
{
|
2012-07-13 01:34:14 +02:00
|
|
|
if (!COMPLEX(THIS))
|
2012-07-09 01:23:24 +02:00
|
|
|
{
|
2012-07-13 01:34:14 +02:00
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
/*case GB_T_FLOAT:
|
|
|
|
conv->_float.value = gsl_blas_dnrm2(MAT(THIS));
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
case GB_T_SINGLE:
|
|
|
|
conv->_single.value = gsl_blas_dnrm2(MAT(THIS));
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
case GB_T_INTEGER:
|
|
|
|
case GB_T_SHORT:
|
|
|
|
case GB_T_BYTE:
|
|
|
|
conv->_integer.value = gsl_blas_dnrm2(MAT(THIS));
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
case GB_T_LONG:
|
|
|
|
conv->_long.value = gsl_blas_dnrm2(MAT(THIS));
|
|
|
|
return FALSE;*/
|
|
|
|
|
|
|
|
case GB_T_STRING:
|
|
|
|
case GB_T_CSTRING:
|
|
|
|
conv->_string.value.addr = _to_string(THIS, type == GB_T_CSTRING);
|
|
|
|
conv->_string.value.start = 0;
|
|
|
|
conv->_string.value.len = GB.StringLength(conv->_string.value.addr);
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
/*case GB_T_FLOAT:
|
|
|
|
conv->_float.value = gsl_blas_dznrm2(CMAT(THIS));
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
case GB_T_SINGLE:
|
|
|
|
conv->_single.value = gsl_blas_dznrm2(CMAT(THIS));
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
case GB_T_INTEGER:
|
|
|
|
case GB_T_SHORT:
|
|
|
|
case GB_T_BYTE:
|
|
|
|
conv->_integer.value = gsl_blas_dznrm2(CMAT(THIS));
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
case GB_T_LONG:
|
|
|
|
conv->_long.value = gsl_blas_dznrm2(CMAT(THIS));
|
|
|
|
return FALSE;*/
|
|
|
|
|
|
|
|
case GB_T_STRING:
|
|
|
|
case GB_T_CSTRING:
|
|
|
|
conv->_string.value.addr = _to_string(THIS, type == GB_T_CSTRING);
|
|
|
|
conv->_string.value.start = 0;
|
|
|
|
conv->_string.value.len = GB.StringLength(conv->_string.value.addr);
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return TRUE;
|
|
|
|
}
|
2012-07-09 01:23:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (type >= GB_T_OBJECT)
|
|
|
|
{
|
2012-07-13 01:34:14 +02:00
|
|
|
if (type == CLASS_Complex)
|
|
|
|
{
|
|
|
|
CCOMPLEX *c = (CCOMPLEX *)conv->_object.value;
|
|
|
|
CMATRIX *m = MATRIX_create(2, 2, FALSE);
|
|
|
|
|
|
|
|
gsl_matrix_set(MAT(m), 0, 0, GSL_REAL(c->number));
|
|
|
|
gsl_matrix_set(MAT(m), 1, 1, GSL_REAL(c->number));
|
|
|
|
gsl_matrix_set(MAT(m), 0, 1, -GSL_IMAG(c->number));
|
|
|
|
gsl_matrix_set(MAT(m), 1, 0, GSL_IMAG(c->number));
|
|
|
|
|
|
|
|
conv->_object.value = m;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
else if (GB.Is(conv->_object.value, CLASS_Array))
|
2012-07-09 01:23:24 +02:00
|
|
|
{
|
|
|
|
GB_ARRAY array = (GB_ARRAY)conv->_object.value;
|
2012-07-13 01:34:14 +02:00
|
|
|
GB_ARRAY array2;
|
|
|
|
int height = GB.Array.Count(array);
|
|
|
|
int width = 0;
|
|
|
|
GB_TYPE atype = GB.Array.Type(array);
|
|
|
|
GB_TYPE atype2;
|
|
|
|
int i, j, w;
|
2012-07-09 01:23:24 +02:00
|
|
|
GB_VALUE temp;
|
|
|
|
void *data;
|
2012-07-13 01:34:14 +02:00
|
|
|
CMATRIX *m;
|
|
|
|
CCOMPLEX *c;
|
|
|
|
bool complex;
|
2012-07-09 01:23:24 +02:00
|
|
|
|
2012-07-13 01:34:14 +02:00
|
|
|
if (atype >= GB_T_OBJECT)
|
2012-07-09 01:23:24 +02:00
|
|
|
{
|
2012-07-13 01:34:14 +02:00
|
|
|
complex = FALSE;
|
|
|
|
|
|
|
|
for (i = 0; i < height; i++)
|
2012-07-09 01:23:24 +02:00
|
|
|
{
|
|
|
|
data = GB.Array.Get(array, i);
|
2012-07-13 01:34:14 +02:00
|
|
|
array2 = *((void **)data);
|
|
|
|
if (!array2 || !GB.Is(array2, CLASS_Array))
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
w = GB.Array.Count(array2);
|
|
|
|
if (w > width)
|
|
|
|
width = w;
|
|
|
|
|
|
|
|
atype2 = GB.Array.Type(array2);
|
|
|
|
|
|
|
|
if (atype2 == GB_T_VARIANT || atype2 == CLASS_Complex)
|
|
|
|
complex = TRUE;
|
|
|
|
else if (!(atype2 > GB_T_BOOLEAN && atype2 <= GB_T_FLOAT))
|
|
|
|
return TRUE;
|
2012-07-09 01:23:24 +02:00
|
|
|
}
|
|
|
|
|
2012-07-13 01:34:14 +02:00
|
|
|
//fprintf(stderr, "create: %d %d %d\n", width, height, complex);
|
|
|
|
m = MATRIX_create(width, height, complex);
|
|
|
|
|
|
|
|
for (i = 0; i < height; i++)
|
|
|
|
{
|
|
|
|
array2 = *((void **)GB.Array.Get(array, i));
|
|
|
|
atype2 = GB.Array.Type(array2);
|
|
|
|
w = GB.Array.Count(array2);
|
|
|
|
|
|
|
|
if (atype2 > GB_T_BOOLEAN && atype2 <= GB_T_FLOAT)
|
|
|
|
{
|
|
|
|
for (j = 0; j < w; j++)
|
|
|
|
{
|
|
|
|
data = GB.Array.Get(array2, j);
|
|
|
|
GB.ReadValue(&temp, data, atype2);
|
|
|
|
GB.Conv(&temp, GB_T_FLOAT);
|
|
|
|
if (complex)
|
|
|
|
gsl_matrix_complex_set(CMAT(m), i, j, gsl_complex_rect(temp._float.value, 0));
|
|
|
|
else
|
|
|
|
gsl_matrix_set(MAT(m), i, j, temp._float.value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (atype2 == GB_T_VARIANT)
|
|
|
|
{
|
|
|
|
for (j = 0; j < w; j++)
|
|
|
|
{
|
|
|
|
GB.ReadValue(&temp, GB.Array.Get(array2, j), atype2);
|
|
|
|
GB.BorrowValue(&temp);
|
|
|
|
GB.Conv(&temp, CLASS_Complex);
|
|
|
|
c = temp._object.value;
|
|
|
|
if (c)
|
|
|
|
gsl_matrix_complex_set(CMAT(m), i, j, c->number);
|
|
|
|
else
|
|
|
|
gsl_matrix_complex_set(CMAT(m), i, j, COMPLEX_zero);
|
|
|
|
GB.ReleaseValue(&temp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (atype2 == CLASS_Complex)
|
|
|
|
{
|
|
|
|
for (j = 0; j < w; j++)
|
|
|
|
{
|
|
|
|
c = *((CCOMPLEX **)GB.Array.Get(array2, j));
|
|
|
|
if (c)
|
|
|
|
gsl_matrix_complex_set(CMAT(m), i, j, c->number);
|
|
|
|
else
|
|
|
|
gsl_matrix_complex_set(CMAT(m), i, j, COMPLEX_zero);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
conv->_object.value = m;
|
2012-07-09 01:23:24 +02:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-07-13 01:34:14 +02:00
|
|
|
else if (type > GB_T_BOOLEAN && type <= GB_T_FLOAT)
|
|
|
|
{
|
|
|
|
CMATRIX *m = MATRIX_create(2, 2, FALSE);
|
|
|
|
double value;
|
|
|
|
|
|
|
|
if (type == GB_T_FLOAT)
|
|
|
|
value = conv->_float.value;
|
|
|
|
else if (type == GB_T_SINGLE)
|
|
|
|
value = conv->_single.value;
|
|
|
|
else
|
|
|
|
value = conv->_integer.value;
|
|
|
|
|
|
|
|
gsl_matrix_set(MAT(m), 0, 0, value);
|
|
|
|
gsl_matrix_set(MAT(m), 1, 1, value);
|
|
|
|
|
|
|
|
conv->_object.value = m;
|
|
|
|
return FALSE;
|
|
|
|
}
|
2012-07-09 01:23:24 +02:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2012-07-13 01:34:14 +02:00
|
|
|
BEGIN_METHOD(Matrix_new, GB_INTEGER height; GB_INTEGER width; GB_BOOLEAN complex)
|
2012-07-09 01:23:24 +02:00
|
|
|
|
2012-07-13 01:34:14 +02:00
|
|
|
bool complex = VARGOPT(complex, FALSE);
|
|
|
|
int h = VARGOPT(height, 2);
|
|
|
|
int w = VARGOPT(width, 2);
|
|
|
|
|
|
|
|
if (h < 1) h = 1;
|
|
|
|
if (w < 1) w = 1;
|
|
|
|
|
|
|
|
THIS->complex = complex;
|
|
|
|
|
|
|
|
if (!complex)
|
|
|
|
THIS->matrix = gsl_matrix_calloc(h, w);
|
2012-07-09 01:23:24 +02:00
|
|
|
else
|
2012-07-13 01:34:14 +02:00
|
|
|
THIS->matrix = gsl_matrix_complex_calloc(h, w);
|
|
|
|
|
2012-07-09 01:23:24 +02:00
|
|
|
END_METHOD
|
|
|
|
|
|
|
|
|
2012-07-13 01:34:14 +02:00
|
|
|
BEGIN_METHOD_VOID(Matrix_free)
|
|
|
|
|
|
|
|
if (!COMPLEX(THIS))
|
|
|
|
gsl_matrix_free(MAT(THIS));
|
|
|
|
else
|
|
|
|
gsl_matrix_complex_free(CMAT(THIS));
|
2012-07-09 01:23:24 +02:00
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
|
|
|
|
2012-07-13 01:34:14 +02:00
|
|
|
BEGIN_PROPERTY(Matrix_Width)
|
|
|
|
|
|
|
|
GB.ReturnInteger(WIDTH(THIS));
|
2012-07-09 01:23:24 +02:00
|
|
|
|
|
|
|
END_PROPERTY
|
|
|
|
|
2012-07-13 01:34:14 +02:00
|
|
|
|
|
|
|
BEGIN_PROPERTY(Matrix_Height)
|
|
|
|
|
|
|
|
GB.ReturnInteger(HEIGHT(THIS));
|
|
|
|
|
|
|
|
END_PROPERTY
|
|
|
|
|
|
|
|
|
|
|
|
BEGIN_METHOD_VOID(Matrix_Copy)
|
2012-07-09 01:23:24 +02:00
|
|
|
|
|
|
|
GB.ReturnObject(MATRIX_copy(THIS));
|
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
|
|
|
|
2012-07-13 01:34:14 +02:00
|
|
|
BEGIN_METHOD(Matrix_get, GB_INTEGER i; GB_INTEGER j)
|
|
|
|
|
|
|
|
int w = WIDTH(THIS), h = HEIGHT(THIS);
|
|
|
|
int i = VARG(i), j = VARG(j);
|
2012-07-09 01:23:24 +02:00
|
|
|
|
2012-07-13 01:34:14 +02:00
|
|
|
if (i < 0 || i >= h || j < 0 || j >= w)
|
2012-07-09 01:23:24 +02:00
|
|
|
{
|
2012-07-13 01:34:14 +02:00
|
|
|
GB.Error(GB_ERR_BOUND);
|
2012-07-09 01:23:24 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-07-13 01:34:14 +02:00
|
|
|
if (!COMPLEX(THIS))
|
|
|
|
GB.ReturnFloat(gsl_matrix_get(MAT(THIS), i, j));
|
|
|
|
else
|
|
|
|
GB.ReturnObject(COMPLEX_create(gsl_matrix_complex_get(CMAT(THIS), i, j)));
|
|
|
|
|
|
|
|
GB.ReturnConvVariant();
|
2012-07-09 01:23:24 +02:00
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
|
|
|
|
2012-07-13 01:34:14 +02:00
|
|
|
BEGIN_METHOD(Matrix_put, GB_VARIANT value; GB_INTEGER i; GB_INTEGER j)
|
|
|
|
|
|
|
|
int w = WIDTH(THIS), h = HEIGHT(THIS);
|
|
|
|
int i = VARG(i), j = VARG(j);
|
|
|
|
GB_VALUE *value = (GB_VALUE *)ARG(value);
|
|
|
|
int type;
|
|
|
|
gsl_complex z;
|
|
|
|
double x;
|
|
|
|
|
|
|
|
if (i < 0 || i >= h || j < 0 || j >= w)
|
|
|
|
{
|
|
|
|
GB.Error(GB_ERR_BOUND);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
type = COMPLEX_get_value(value, &x, &z);
|
|
|
|
|
|
|
|
if (type == CGV_ERR)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (type == CGV_COMPLEX)
|
|
|
|
{
|
|
|
|
ensure_complex(THIS);
|
|
|
|
gsl_matrix_complex_set(CMAT(THIS), i, j, z);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (COMPLEX(THIS))
|
|
|
|
gsl_matrix_complex_set(CMAT(THIS), i, j, z);
|
|
|
|
else
|
|
|
|
gsl_matrix_set(MAT(THIS), i, j, x);
|
|
|
|
}
|
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
|
|
|
|
|
|
|
BEGIN_METHOD(Matrix_Scale, GB_VALUE value)
|
|
|
|
|
|
|
|
GB_VALUE *value = (GB_VALUE *)ARG(value);
|
|
|
|
int type;
|
|
|
|
gsl_complex z;
|
|
|
|
double x;
|
|
|
|
|
|
|
|
type = COMPLEX_get_value(value, &x, &z);
|
|
|
|
|
|
|
|
if (type == CGV_ERR)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (type == CGV_COMPLEX)
|
|
|
|
{
|
|
|
|
ensure_complex(THIS);
|
|
|
|
gsl_matrix_complex_scale(CMAT(THIS), z);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (COMPLEX(THIS))
|
|
|
|
gsl_matrix_complex_scale(CMAT(THIS), z);
|
|
|
|
else
|
|
|
|
gsl_matrix_scale(MAT(THIS), x);
|
|
|
|
}
|
|
|
|
|
|
|
|
GB.ReturnObject(THIS);
|
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
|
|
|
BEGIN_METHOD(Matrix_Equal, GB_OBJECT matrix)
|
|
|
|
|
|
|
|
CMATRIX *m = VARG(matrix);
|
|
|
|
bool ca, cb;
|
|
|
|
|
|
|
|
if (GB.CheckObject(m))
|
|
|
|
return;
|
2012-07-09 01:23:24 +02:00
|
|
|
|
2012-07-13 01:34:14 +02:00
|
|
|
if (WIDTH(THIS) != WIDTH(m) || HEIGHT(THIS) != HEIGHT(m))
|
2012-07-09 01:23:24 +02:00
|
|
|
{
|
2012-07-13 01:34:14 +02:00
|
|
|
GB.ReturnBoolean(FALSE);
|
2012-07-09 01:23:24 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-07-13 01:34:14 +02:00
|
|
|
ca = !COMPLEX(THIS);
|
|
|
|
cb = !COMPLEX(m);
|
|
|
|
|
|
|
|
if (ca && cb)
|
|
|
|
{
|
|
|
|
GB.ReturnBoolean(gsl_matrix_equal(MAT(THIS), MAT(m)));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CMATRIX *a, *b;
|
|
|
|
|
|
|
|
if (ca)
|
|
|
|
a = MATRIX_convert_to_complex(THIS);
|
|
|
|
else
|
|
|
|
a = THIS;
|
|
|
|
|
|
|
|
if (cb)
|
|
|
|
b = MATRIX_convert_to_complex(m);
|
|
|
|
else
|
|
|
|
b = m;
|
|
|
|
|
|
|
|
GB.ReturnBoolean(gsl_matrix_complex_equal(CMAT(a), CMAT(b)));
|
|
|
|
|
|
|
|
if (ca) GB.Unref(POINTER(&a));
|
|
|
|
if (cb) GB.Unref(POINTER(&b));
|
|
|
|
}
|
|
|
|
|
2012-07-09 01:23:24 +02:00
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
2012-07-13 01:34:14 +02:00
|
|
|
|
|
|
|
BEGIN_PROPERTY(Matrix_Handle)
|
|
|
|
|
|
|
|
GB.ReturnPointer(THIS->matrix);
|
|
|
|
|
|
|
|
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));
|
|
|
|
|
|
|
|
if (COMPLEX(m))
|
|
|
|
gsl_matrix_complex_set_identity(CMAT(m));
|
|
|
|
else
|
|
|
|
gsl_matrix_set_identity(MAT(m));
|
|
|
|
|
|
|
|
GB.ReturnObject(m);
|
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
|
|
|
|
|
|
|
BEGIN_METHOD(Matrix_Row, GB_INTEGER row)
|
|
|
|
|
|
|
|
int row = VARG(row);
|
|
|
|
|
|
|
|
if (row < 0 || row >= HEIGHT(THIS))
|
|
|
|
{
|
|
|
|
GB.Error(GB_ERR_BOUND);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool complex = COMPLEX(THIS);
|
|
|
|
CVECTOR *v = VECTOR_create(WIDTH(THIS), complex, FALSE);
|
|
|
|
|
|
|
|
if (complex)
|
|
|
|
gsl_matrix_complex_get_row(CVEC(v), CMAT(THIS), row);
|
|
|
|
else
|
|
|
|
gsl_matrix_get_row(VEC(v), MAT(THIS), row);
|
|
|
|
|
|
|
|
GB.ReturnObject(v);
|
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
|
|
|
BEGIN_METHOD(Matrix_Column, GB_INTEGER column)
|
|
|
|
|
|
|
|
int column = VARG(column);
|
|
|
|
|
|
|
|
if (column < 0 || column >= WIDTH(THIS))
|
|
|
|
{
|
|
|
|
GB.Error(GB_ERR_BOUND);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool complex = COMPLEX(THIS);
|
|
|
|
CVECTOR *v = VECTOR_create(HEIGHT(THIS), complex, FALSE);
|
|
|
|
|
|
|
|
if (complex)
|
|
|
|
gsl_matrix_complex_get_col(CVEC(v), CMAT(THIS), column);
|
|
|
|
else
|
|
|
|
gsl_matrix_get_col(VEC(v), MAT(THIS), column);
|
|
|
|
|
|
|
|
GB.ReturnObject(v);
|
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
|
|
|
BEGIN_METHOD(Matrix_SetRow, GB_INTEGER row; GB_OBJECT vector)
|
|
|
|
|
|
|
|
int row = VARG(row);
|
|
|
|
|
|
|
|
if (row < 0 || row >= HEIGHT(THIS))
|
|
|
|
{
|
|
|
|
GB.Error(GB_ERR_BOUND);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
CVECTOR *v = (CVECTOR *)VARG(vector);
|
|
|
|
|
|
|
|
if (GB.CheckObject(v))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (SIZE(v) != WIDTH(THIS))
|
|
|
|
{
|
|
|
|
GB.Error("Vector size does not match matrix width");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool complex = COMPLEX(THIS);
|
|
|
|
|
|
|
|
if (complex)
|
|
|
|
{
|
|
|
|
VECTOR_ensure_complex(v);
|
|
|
|
gsl_matrix_complex_set_row(CMAT(THIS), row, CVEC(v));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (VECTOR_ensure_not_complex(v))
|
|
|
|
{
|
|
|
|
GB.Error(GB_ERR_TYPE, "Float", "Complex");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
gsl_matrix_set_row(MAT(THIS), row, VEC(v));
|
|
|
|
}
|
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
|
|
|
BEGIN_METHOD(Matrix_SetColumn, GB_INTEGER column; GB_OBJECT vector)
|
|
|
|
|
|
|
|
int column = VARG(column);
|
|
|
|
|
|
|
|
if (column < 0 || column >= WIDTH(THIS))
|
|
|
|
{
|
|
|
|
GB.Error(GB_ERR_BOUND);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
CVECTOR *v = (CVECTOR *)VARG(vector);
|
|
|
|
|
|
|
|
if (GB.CheckObject(v))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (SIZE(v) != HEIGHT(THIS))
|
|
|
|
{
|
|
|
|
GB.Error("Vector size does not match matrix height");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool complex = COMPLEX(THIS);
|
|
|
|
|
|
|
|
if (complex)
|
|
|
|
{
|
|
|
|
VECTOR_ensure_complex(v);
|
|
|
|
gsl_matrix_complex_set_col(CMAT(THIS), column, CVEC(v));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (VECTOR_ensure_not_complex(v))
|
|
|
|
{
|
|
|
|
GB.Error(GB_ERR_TYPE, "Float", "Complex");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
gsl_matrix_set_col(MAT(THIS), column, VEC(v));
|
|
|
|
}
|
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
|
|
|
|
|
|
|
GB_DESC MatrixDesc[] =
|
2012-07-09 01:23:24 +02:00
|
|
|
{
|
2012-07-13 01:34:14 +02:00
|
|
|
GB_DECLARE("Matrix", sizeof(CMATRIX)),
|
2012-07-09 01:23:24 +02:00
|
|
|
|
2012-07-13 01:34:14 +02:00
|
|
|
GB_METHOD("_new", NULL, Matrix_new, "[(Width)i(Height)i(Complex)b]"),
|
|
|
|
GB_METHOD("_free", NULL, Matrix_free, NULL),
|
|
|
|
//GB_STATIC_METHOD("_call", "Vector", Matrix_call, "(Value)f."),
|
|
|
|
GB_METHOD("Copy", "Matrix", Matrix_Copy, NULL),
|
|
|
|
|
|
|
|
GB_STATIC_METHOD("Identity", "Matrix", Matrix_Identity, "[(Width)i(Height)i(Complex)b]"),
|
|
|
|
|
|
|
|
GB_PROPERTY_READ("Width", "i", Matrix_Width),
|
|
|
|
GB_PROPERTY_READ("Height", "i", Matrix_Height),
|
|
|
|
GB_PROPERTY_READ("Handle", "p", Matrix_Handle),
|
|
|
|
|
|
|
|
GB_METHOD("_get", "v", Matrix_get, "(I)i(J)i"),
|
|
|
|
GB_METHOD("_put", NULL, Matrix_put, "(Value)v(I)i(J)i"),
|
|
|
|
|
|
|
|
GB_METHOD("Scale", "Matrix", Matrix_Scale, "(Value)v"),
|
|
|
|
GB_METHOD("Equal", "b", Matrix_Equal, "(Matrix)Matrix;"),
|
2012-07-09 01:23:24 +02:00
|
|
|
|
2012-07-13 01:34:14 +02:00
|
|
|
GB_METHOD("Row", "Vector", Matrix_Row, "(Row)i"),
|
|
|
|
GB_METHOD("Column", "Vector", Matrix_Column, "(Column)i"),
|
|
|
|
GB_METHOD("SetRow", NULL, Matrix_SetRow, "(Row)i(Vector)Vector;"),
|
|
|
|
GB_METHOD("SetColumn", NULL, Matrix_SetColumn, "(Column)i(Vector)Vector;"),
|
2012-07-09 01:23:24 +02:00
|
|
|
|
|
|
|
GB_INTERFACE("_convert", &_convert),
|
|
|
|
|
|
|
|
GB_END_DECLARE
|
|
|
|
};
|