From c171c078e509cfbb639091e2dbcd618d82905cea Mon Sep 17 00:00:00 2001 From: Whiteknight Date: Fri, 20 Aug 2010 11:13:44 -0400 Subject: [PATCH] several bug fixes to make a non-trivial example work. GEMM calls weren't respecting lazy transposes, so force that to happen in several places. Also both Gemm methods were returning the wrong value and not respecting forced conversions on parameter C --- src/pmc/complexmatrix2d.pmc | 53 +++++++++++++++++++++++++++++++------ src/pmc/nummatrix2d.pmc | 50 +++++++++++++++++++--------------- src/pmc/pmcmatrix2d.pmc | 30 +++++++++++++++++++++ 3 files changed, 103 insertions(+), 30 deletions(-) diff --git a/src/pmc/complexmatrix2d.pmc b/src/pmc/complexmatrix2d.pmc index dceb0d4..688df76 100644 --- a/src/pmc/complexmatrix2d.pmc +++ b/src/pmc/complexmatrix2d.pmc @@ -36,11 +36,44 @@ get_complex_value_from_pmc(PARROT_INTERP, PMC * value, FLOATVAL * real, FLOATVAL } } +/* If the matrix is lazily transposed, actually transpose the physical memory + layout. This is necessary for calculations, especially BLAS calculations, + which aren't lazy-transpose-aware. */ +static void +normalize_lazy_transpose(PARROT_INTERP, PMC * self) +{ + DECLATTRS(self, attrs); + if (IS_TRANSPOSED(attrs->flags)) { + const INTVAL rows_size = attrs->rows; + const INTVAL cols_size = attrs->cols; + const INTVAL size = rows_size * cols_size; + FLOATVAL * const new_s = ALLOCATE_STORAGE(size); + FLOATVAL * const old_s = attrs->storage; + INTVAL i, j; + + for (i = 0; i < rows_size; ++i) { + for (j = 0; j < cols_size; ++j) { + R_ITEM_XY_COLMAJOR(new_s, rows_size, cols_size, i, j) = + R_ITEM_XY_ROWMAJOR(old_s, rows_size, cols_size, i, j); + I_ITEM_XY_COLMAJOR(new_s, rows_size, cols_size, i, j) = + I_ITEM_XY_ROWMAJOR(old_s, rows_size, cols_size, i, j); + } + } + attrs->storage = new_s; + mem_sys_free(old_s); + FLAG_CLEAR(attrs->flags, FLAG_TRANSPOSED); + } +} + static PMC * -convert_to_ComplexMatrix2D(PARROT_INTERP, PMC * p) +convert_to_ComplexMatrix2D(PARROT_INTERP, PMC * p, INTVAL forcecopy) { - if (p->vtable->base_type == __PLA_Type_ComplexMatrix2D) + if (p->vtable->base_type == __PLA_Type_ComplexMatrix2D) { + normalize_lazy_transpose(interp, p); + if (forcecopy) + return VTABLE_clone(interp, p); return p; + } else if (!VTABLE_does(interp, p, CONST_STRING(interp, "matrix"))) Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_OUT_OF_BOUNDS, PLATYPENAME ": cannot convert unknown PMC type"); @@ -52,6 +85,7 @@ convert_to_ComplexMatrix2D(PARROT_INTERP, PMC * p) } } + /* Resize the matrix internal storage to be able to hold a point at position (x, y). The matrix grows but does not shrink. New spaces in the matrix are initialized to 0.0. Parameters x and y are the indices that are trying @@ -198,6 +232,7 @@ call_gemm(PARROT_INTERP, FLOATVAL alpha_r, FLOATVAL alpha_i, PMC * A, PMC *B, alpha_p[1] = alpha_i; beta_p[0] = beta_r; beta_p[1] = beta_i; + fprintf(stderr, "%f %f %f %f\n", alpha_r, alpha_i, beta_r, beta_i); cblas_zgemm(CblasRowMajor, IS_TRANSPOSED_BLAS(attrs_a->flags), IS_TRANSPOSED_BLAS(attrs_b->flags), @@ -1321,15 +1356,14 @@ Calculates the matrix equation: */ METHOD gemm(PMC *alpha, PMC * A, PMC *B, PMC *beta, PMC *C) { - PMC * const c_out = VTABLE_clone(INTERP, C); FLOATVAL alpha_r, alpha_i, beta_r, beta_i; - A = convert_to_ComplexMatrix2D(interp, A); - B = convert_to_ComplexMatrix2D(interp, B); - C = convert_to_ComplexMatrix2D(interp, C); + A = convert_to_ComplexMatrix2D(interp, A, 0); + B = convert_to_ComplexMatrix2D(interp, B, 0); + C = convert_to_ComplexMatrix2D(interp, C, 1); get_complex_value_from_pmc(interp, alpha, &alpha_r, &alpha_i); get_complex_value_from_pmc(interp, beta, &beta_r, &beta_i); - call_gemm(INTERP, alpha_r, alpha_i, A, B, beta_r, beta_i, c_out); - RETURN(PMC* c_out); + call_gemm(INTERP, alpha_r, alpha_i, A, B, beta_r, beta_i, C); + RETURN(PMC* C); } /* @@ -1431,6 +1465,7 @@ Get a PMCMatrix2D from the current matrix PMC * const meth = VTABLE_find_method(INTERP, d, CONST_STRING(INTERP, "resize")); INTVAL i; Parrot_ext_call(INTERP, meth, "PiII->", d, attrs->rows, attrs->cols); + normalize_lazy_transpose(INTERP, SELF); for (i = 0; i < totalsize; i++) { const FLOATVAL f = VTABLE_get_number_keyed_int(INTERP, SELF, i); VTABLE_set_number_keyed_int(INTERP, d, i, f); @@ -1440,6 +1475,7 @@ Get a PMCMatrix2D from the current matrix METHOD convert_to_complex_matrix() { PMC * const d = VTABLE_clone(INTERP, SELF); + normalize_lazy_transpose(INTERP, d); RETURN(PMC * d); } @@ -1450,6 +1486,7 @@ Get a PMCMatrix2D from the current matrix PMC * const meth = VTABLE_find_method(INTERP, d, CONST_STRING(INTERP, "resize")); INTVAL i; Parrot_ext_call(INTERP, meth, "PiII->", d, attrs->rows, attrs->cols); + normalize_lazy_transpose(INTERP, SELF); for (i = 0; i < totalsize; i++) { PMC * const p = VTABLE_get_pmc_keyed_int(INTERP, SELF, i); VTABLE_set_pmc_keyed_int(INTERP, d, i, p); diff --git a/src/pmc/nummatrix2d.pmc b/src/pmc/nummatrix2d.pmc index 3dac196..f6f1b00 100644 --- a/src/pmc/nummatrix2d.pmc +++ b/src/pmc/nummatrix2d.pmc @@ -18,22 +18,6 @@ INTVAL __PLA_Type_NumMatrix2D; -static PMC * -convert_to_NumMatrix2D(PARROT_INTERP, PMC * p) -{ - if (p->vtable->base_type == __PLA_Type_NumMatrix2D) - return p; - else if (!VTABLE_does(interp, p, CONST_STRING(interp, "matrix"))) - Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_OUT_OF_BOUNDS, - PLATYPENAME ": cannot convert unknown PMC type"); - else { - PMC * const meth = VTABLE_find_method(interp, p, CONST_STRING(interp, "convert_to_number_matrix")); - PMC * dest = PMCNULL; - Parrot_ext_call(interp, meth, "Pi->P", p, &dest); - return dest; - } -} - /* Resize the matrix internal storage to be able to hold a point at position (x, y). The matrix grows but does not shrink. New spaces in the matrix are initialized to 0.0. Parameters x and y are the indices that are trying @@ -102,6 +86,26 @@ normalize_lazy_transpose(PARROT_INTERP, PMC * self) } } +static PMC * +convert_to_NumMatrix2D(PARROT_INTERP, PMC * p, INTVAL forcecopy) +{ + if (p->vtable->base_type == __PLA_Type_NumMatrix2D) { + normalize_lazy_transpose(interp, p); + if (forcecopy) + return VTABLE_clone(interp, p); + return p; + } + else if (!VTABLE_does(interp, p, CONST_STRING(interp, "matrix"))) + Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_OUT_OF_BOUNDS, + PLATYPENAME ": cannot convert unknown PMC type"); + else { + PMC * const meth = VTABLE_find_method(interp, p, CONST_STRING(interp, "convert_to_number_matrix")); + PMC * dest = PMCNULL; + Parrot_ext_call(interp, meth, "Pi->P", p, &dest); + return dest; + } +} + /* Initialize the PMC from an array, filling the matrix row-at-a-time */ static void init_from_pmc_array(PARROT_INTERP, PMC * self, INTVAL rows_size, @@ -1221,12 +1225,11 @@ Calculates the matrix equation: */ METHOD gemm(FLOATVAL alpha, PMC * A, PMC *B, FLOATVAL beta, PMC *C) { - PMC * const c_out = VTABLE_clone(INTERP, C); - A = convert_to_NumMatrix2D(interp, A); - B = convert_to_NumMatrix2D(interp, B); - C = convert_to_NumMatrix2D(interp, C); - call_gemm(INTERP, alpha, A, B, beta, c_out); - RETURN(PMC* c_out); + A = convert_to_NumMatrix2D(interp, A, 0); + B = convert_to_NumMatrix2D(interp, B, 0); + C = convert_to_NumMatrix2D(interp, C, 1); + call_gemm(INTERP, alpha, A, B, beta, C); + RETURN(PMC* C); } /* @@ -1317,6 +1320,7 @@ Get a PMCMatrix2D from the current matrix METHOD convert_to_number_matrix() { PMC * const d = VTABLE_clone(INTERP, SELF); + normalize_lazy_transpose(INTERP, d); RETURN(PMC * d); } @@ -1327,6 +1331,7 @@ Get a PMCMatrix2D from the current matrix PMC * const meth = VTABLE_find_method(INTERP, d, CONST_STRING(INTERP, "resize")); INTVAL i; Parrot_ext_call(INTERP, meth, "PiII->", d, attrs->rows, attrs->cols); + normalize_lazy_transpose(INTERP, SELF); for (i = 0; i < totalsize; i++) { const FLOATVAL f = VTABLE_get_number_keyed_int(INTERP, SELF, i); VTABLE_set_number_keyed_int(INTERP, d, i, f); @@ -1341,6 +1346,7 @@ Get a PMCMatrix2D from the current matrix PMC * const meth = VTABLE_find_method(INTERP, d, CONST_STRING(INTERP, "resize")); INTVAL i; Parrot_ext_call(INTERP, meth, "PiII->", d, attrs->rows, attrs->cols); + normalize_lazy_transpose(INTERP, SELF); for (i = 0; i < totalsize; i++) { const FLOATVAL f = VTABLE_get_number_keyed_int(INTERP, SELF, i); VTABLE_set_number_keyed_int(INTERP, d, i, f); diff --git a/src/pmc/pmcmatrix2d.pmc b/src/pmc/pmcmatrix2d.pmc index e908510..d95efd5 100644 --- a/src/pmc/pmcmatrix2d.pmc +++ b/src/pmc/pmcmatrix2d.pmc @@ -80,6 +80,33 @@ init_from_pmc_array(PARROT_INTERP, PMC * self, INTVAL rows_size, INTVAL cols_siz } } +/* If the matrix is lazily transposed, actually transpose the physical memory + layout. This is necessary for calculations, especially BLAS calculations, + which aren't lazy-transpose-aware. */ +static void +normalize_lazy_transpose(PARROT_INTERP, PMC * self) +{ + DECLATTRS(self, attrs); + if (IS_TRANSPOSED(attrs->flags)) { + const INTVAL rows_size = attrs->rows; + const INTVAL cols_size = attrs->cols; + const INTVAL size = rows_size * cols_size; + FLOATVAL * const new_s = ALLOCATE_STORAGE(size); + FLOATVAL * const old_s = attrs->storage; + INTVAL i, j; + + for (i = 0; i < rows_size; ++i) { + for (j = 0; j < cols_size; ++j) { + ITEM_XY_COLMAJOR(new_s, rows_size, cols_size, i, j) = + ITEM_XY_ROWMAJOR(old_s, rows_size, cols_size, i, j); + } + } + attrs->storage = new_s; + mem_sys_free(old_s); + FLAG_CLEAR(attrs->flags, FLAG_TRANSPOSED); + } +} + pmclass PMCMatrix2D dynpmc auto_attrs provides matrix { ATTR PMC ** storage; @@ -699,6 +726,7 @@ Get a PMCMatrix2D from the current matrix PMC * const meth = VTABLE_find_method(INTERP, d, CONST_STRING(INTERP, "resize")); INTVAL i; Parrot_ext_call(INTERP, meth, "PiII->", d, attrs->rows, attrs->cols); + normalize_lazy_transpose(INTERP, SELF); for (i = 0; i < totalsize; i++) { const FLOATVAL f = VTABLE_get_number_keyed_int(INTERP, SELF, i); VTABLE_set_number_keyed_int(INTERP, d, i, f); @@ -713,6 +741,7 @@ Get a PMCMatrix2D from the current matrix PMC * const meth = VTABLE_find_method(INTERP, d, CONST_STRING(INTERP, "resize")); INTVAL i; Parrot_ext_call(INTERP, meth, "PiII->", d, attrs->rows, attrs->cols); + normalize_lazy_transpose(INTERP, SELF); for (i = 0; i < totalsize; i++) { PMC * const p = VTABLE_get_pmc_keyed_int(INTERP, SELF, i); VTABLE_set_pmc_keyed_int(INTERP, d, i, p); @@ -722,6 +751,7 @@ Get a PMCMatrix2D from the current matrix METHOD convert_to_pmc_matrix() { PMC * const d = VTABLE_clone(INTERP, SELF); + normalize_lazy_transpose(INTERP, d); RETURN(PMC * d); }