[pure-lang-svn] SF.net SVN: pure-lang:[833] pure/trunk
Status: Beta
Brought to you by:
agraef
From: <ag...@us...> - 2008-09-23 05:54:41
|
Revision: 833 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=833&view=rev Author: agraef Date: 2008-09-23 05:54:38 +0000 (Tue, 23 Sep 2008) Log Message: ----------- Make the matrix construction functions in the library throw a 'bad_matrix_value' exception in case of dimension mismatch. Modified Paths: -------------- pure/trunk/lib/primitives.pure pure/trunk/runtime.cc pure/trunk/runtime.h Modified: pure/trunk/lib/primitives.pure =================================================================== --- pure/trunk/lib/primitives.pure 2008-09-23 05:31:30 UTC (rev 832) +++ pure/trunk/lib/primitives.pure 2008-09-23 05:54:38 UTC (rev 833) @@ -473,7 +473,9 @@ converts it to a list of its elements; otherwise the result is the list of the rows of the matrix. You can also use list2 to convert a matrix to a list of lists. Conversely, matrix xs converts a list of lists or matrices - to the corresponding matrix. Otherwise, the result is a row vector. */ + to the corresponding matrix; otherwise, the result is a row vector. + NOTE: The matrix function may throw a 'bad_matrix_value x' in case of + dimension mismatch, where x denotes the offending submatrix. */ list x::matrix = [x!i|i=0..#x-1] if rowvectorp x; = rows x otherwise; @@ -520,7 +522,9 @@ /* Construct matrices from lists of rows and columns. These take either scalars or submatrices as inputs; corresponding dimensions must match. rowcat combines submatrices vertically, like {x;y}; colcat combines them - horizontally, like {x,y}. */ + horizontally, like {x,y}. NOTE: Like the built-in matrix constructs, these + operations may throw a 'bad_matrix_value x' in case of dimension mismatch, + where x denotes the offending submatrix. */ extern expr* matrix_rows(expr *x) = rowcat; extern expr* matrix_columns(expr *x) = colcat; Modified: pure/trunk/runtime.cc =================================================================== --- pure/trunk/runtime.cc 2008-09-23 05:31:30 UTC (rev 832) +++ pure/trunk/runtime.cc 2008-09-23 05:54:38 UTC (rev 833) @@ -4568,13 +4568,227 @@ return y; } +static pure_expr *matrix_rowsv(uint32_t n, pure_expr **xs) +{ + int k = -1; + size_t nrows = 0, ncols = 0; + int32_t target = 0; + bool have_matrix = false; + pure_expr *x = 0; + for (size_t i = 0; i < n; i++) { + x = xs[i]; + switch (x->tag) { + case EXPR::MATRIX: { + gsl_matrix_symbolic *mp = (gsl_matrix_symbolic*)x->data.mat.p; + if (mp->size1 > 0 && mp->size2 > 0) { + if (k >= 0 && mp->size2 != (size_t)k) + goto err; + nrows += mp->size1; k = mp->size2; + set_target_type(target, EXPR::MATRIX); + have_matrix = true; + } + break; + } +#ifdef HAVE_GSL + case EXPR::DBL: + set_target_type(target, EXPR::DMATRIX); + if (k >= 0 && k != 1) goto err; + nrows++; k = 1; + break; + case EXPR::INT: + set_target_type(target, EXPR::IMATRIX); + if (k >= 0 && k != 1) goto err; + nrows++; k = 1; + break; + case EXPR::APP: { + double a, b; + if (k >= 0 && k != 1) goto err; + nrows++; k = 1; + if (get_complex(x, a, b)) + set_target_type(target, EXPR::CMATRIX); + else + set_target_type(target, EXPR::MATRIX); + break; + } + case EXPR::DMATRIX: { + gsl_matrix *mp = (gsl_matrix*)x->data.mat.p; + if (mp->size1 > 0 && mp->size2 > 0) { + if (k >= 0 && mp->size2 != (size_t)k) + goto err; + nrows += mp->size1; k = mp->size2; + set_target_type(target, EXPR::DMATRIX); + have_matrix = true; + } + break; + } + case EXPR::CMATRIX: { + gsl_matrix_complex *mp = (gsl_matrix_complex*)x->data.mat.p; + if (mp->size1 > 0 && mp->size2 > 0) { + if (k >= 0 && mp->size2 != (size_t)k) + goto err; + nrows += mp->size1; k = mp->size2; + set_target_type(target, EXPR::CMATRIX); + have_matrix = true; + } + break; + } + case EXPR::IMATRIX: { + gsl_matrix_int *mp = (gsl_matrix_int*)x->data.mat.p; + if (mp->size1 > 0 && mp->size2 > 0) { + if (k >= 0 && mp->size2 != (size_t)k) + goto err; + nrows += mp->size1; k = mp->size2; + set_target_type(target, EXPR::IMATRIX); + have_matrix = true; + } + break; + } +#endif + default: + if (k >= 0 && k != 1) goto err; + nrows++; k = 1; + set_target_type(target, EXPR::MATRIX); + break; + } + } + if (n == 1 && have_matrix) return xs[0]; + if (k < 0) k = 0; + ncols = k; + if (target == 0) target = EXPR::MATRIX; + switch (target) { + case EXPR::MATRIX: + return symbolic_matrix_rows(nrows, ncols, n, xs); +#ifdef HAVE_GSL + case EXPR::DMATRIX: + return double_matrix_rows(nrows, ncols, n, xs); + case EXPR::CMATRIX: + return complex_matrix_rows(nrows, ncols, n, xs); + case EXPR::IMATRIX: + return int_matrix_rows(nrows, ncols, n, xs); +#endif + default: + assert(0 && "this can't happen"); + return 0; + } + err: + pure_throw(bad_matrix_exception(x)); + return 0; +} + +static pure_expr *matrix_columnsv(uint32_t n, pure_expr **xs) +{ + int k = -1; + size_t nrows = 0, ncols = 0; + int32_t target = 0; + bool have_matrix = false; + pure_expr *x = 0; + for (size_t i = 0; i < n; i++) { + x = xs[i]; + switch (x->tag) { + case EXPR::MATRIX: { + gsl_matrix_symbolic *mp = (gsl_matrix_symbolic*)x->data.mat.p; + if (mp->size1 > 0 && mp->size2 > 0) { + if (k >= 0 && mp->size1 != (size_t)k) + goto err; + ncols += mp->size2; k = mp->size1; + set_target_type(target, EXPR::MATRIX); + have_matrix = true; + } + break; + } +#ifdef HAVE_GSL + case EXPR::DBL: + set_target_type(target, EXPR::DMATRIX); + if (k >= 0 && k != 1) goto err; + ncols++; k = 1; + break; + case EXPR::INT: + set_target_type(target, EXPR::IMATRIX); + if (k >= 0 && k != 1) goto err; + ncols++; k = 1; + break; + case EXPR::APP: { + double a, b; + if (k >= 0 && k != 1) goto err; + ncols++; k = 1; + if (get_complex(x, a, b)) + set_target_type(target, EXPR::CMATRIX); + else + set_target_type(target, EXPR::MATRIX); + break; + } + case EXPR::DMATRIX: { + gsl_matrix *mp = (gsl_matrix*)x->data.mat.p; + if (mp->size1 > 0 && mp->size2 > 0) { + if (k >= 0 && mp->size1 != (size_t)k) + goto err; + ncols += mp->size2; k = mp->size1; + set_target_type(target, EXPR::DMATRIX); + have_matrix = true; + } + break; + } + case EXPR::CMATRIX: { + gsl_matrix_complex *mp = (gsl_matrix_complex*)x->data.mat.p; + if (mp->size1 > 0 && mp->size2 > 0) { + if (k >= 0 && mp->size1 != (size_t)k) + goto err; + ncols += mp->size2; k = mp->size1; + set_target_type(target, EXPR::CMATRIX); + have_matrix = true; + } + break; + } + case EXPR::IMATRIX: { + gsl_matrix_int *mp = (gsl_matrix_int*)x->data.mat.p; + if (mp->size1 > 0 && mp->size2 > 0) { + if (k >= 0 && mp->size1 != (size_t)k) + goto err; + ncols += mp->size2; k = mp->size1; + set_target_type(target, EXPR::IMATRIX); + have_matrix = true; + } + break; + } +#endif + default: + if (k >= 0 && k != 1) goto err; + ncols++; k = 1; + set_target_type(target, EXPR::MATRIX); + break; + } + } + if (n == 1 && have_matrix) return xs[0]; + if (k < 0) k = 0; + nrows = k; + if (target == 0) target = EXPR::MATRIX; + switch (target) { + case EXPR::MATRIX: + return symbolic_matrix_columns(nrows, ncols, n, xs); +#ifdef HAVE_GSL + case EXPR::DMATRIX: + return double_matrix_columns(nrows, ncols, n, xs); + case EXPR::CMATRIX: + return complex_matrix_columns(nrows, ncols, n, xs); + case EXPR::IMATRIX: + return int_matrix_columns(nrows, ncols, n, xs); +#endif + default: + assert(0 && "this can't happen"); + return 0; + } + err: + pure_throw(bad_matrix_exception(x)); + return 0; +} + extern "C" pure_expr *matrix_rows(pure_expr *xs) { size_t n; pure_expr **elems; if (pure_is_listv(xs, &n, &elems)) { - pure_expr *ret = pure_matrix_rowsv(n, elems); + pure_expr *ret = matrix_rowsv(n, elems); if (elems) free(elems); return ret; } else @@ -4587,7 +4801,7 @@ size_t n; pure_expr **elems; if (pure_is_listv(xs, &n, &elems)) { - pure_expr *ret = pure_matrix_columnsv(n, elems); + pure_expr *ret = matrix_columnsv(n, elems); if (elems) free(elems); return ret; } else Modified: pure/trunk/runtime.h =================================================================== --- pure/trunk/runtime.h 2008-09-23 05:31:30 UTC (rev 832) +++ pure/trunk/runtime.h 2008-09-23 05:54:38 UTC (rev 833) @@ -703,9 +703,9 @@ pure_expr *matrix_subdiag(pure_expr *x, int32_t k); pure_expr *matrix_supdiag(pure_expr *x, int32_t k); -/* Matrix construction. These work like the pure_matrix_rows/ - pure_matrix_columns functions in the public API, but take their input from - a Pure list. */ +/* Matrix construction. These work like the corresponding functions in the + public API, but take their input from a Pure list and raise the appropriate + exception in case of dimension mismatch. */ pure_expr *matrix_rows(pure_expr *xs); pure_expr *matrix_columns(pure_expr *xs); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |