[ofa-general] Re: [PATCH][4] opensm: vector and matrix utilities
Sasha Khapyorsky
sashak at voltaire.com
Sun Nov 30 05:54:40 PST 2008
On 10:44 Tue 11 Nov , Robert Pearson wrote:
> Sasha,
>
> Here is the fourth patch in a series implementing the mesh analysis
> algorithm.
>
> This patch implements
> - create and cleanup methods for polynomial with integer coefficients
> - create and cleanup methods for square matrix with integer
> coefficients
> - create and cleanup methods for square matrix with polynomial
> coefficients
> - routine to compute the determinant of a matrix with polynomial
> coefficients
>
> (Note the determinant is restricted to computing the characteristic
> polynomial)
>
> Regards,
>
> Bob Pearson
>
> Signed-off-by: Bob Pearson <rpearson at systemfabricworks.com>
> ----
> diff --git a/opensm/opensm/osm_mesh.c b/opensm/opensm/osm_mesh.c
> index 6ef397c..5dee1d0 100644
> --- a/opensm/opensm/osm_mesh.c
> +++ b/opensm/opensm/osm_mesh.c
> @@ -49,6 +49,295 @@
> #include <opensm/osm_ucast_lash.h>
>
> /*
> + * poly_alloc
> + *
> + * allocate a polynomial of degree n
> + */
> +static int *poly_alloc(lash_t *p_lash, int n)
> +{
> + osm_log_t *p_log = &p_lash->p_osm->log;
> + int *p;
> +
> + if (!(p = calloc(n+1, sizeof(int)))) {
> + OSM_LOG(p_log, OSM_LOG_ERROR, "Failed allocating poly - out
> of memory\n");
> + }
> +
> + return p;
> +}
> +
> +/*
> + * poly_diff
> + *
> + * return a nonzero value if polynomials differ else 0
> + */
> +static int poly_diff(int n, int *p, switch_t *s)
> +{
> + int i;
> +
> + if (s->node->num_links != n)
> + return 1;
> +
> + for (i = 0; i <= n; i++) {
> + if (s->node->poly[i] != p[i])
> + return 1;
> + }
memcmp(s->node->poly, p, n)?
> +
> + return 0;
> +}
> +
> +/*
> + * m_free
> + *
> + * free a square matrix of rank l
> + */
> +static void m_free(int **m, int l)
> +{
> + int i;
> +
> + if (m) {
> + for (i = 0; i < l; i++) {
> + if (m[i])
> + free(m[i]);
> + }
> + free(m);
> + }
> +}
> +
> +/*
> + * m_alloc
> + *
> + * allocate a square matrix of rank l
> + */
> +static int **m_alloc(lash_t *p_lash, int l)
> +{
> + osm_log_t *p_log = &p_lash->p_osm->log;
> + int i;
> + int **m = NULL;
> +
> + do {
> + if (!(m = calloc(l, sizeof(int *))))
> + break;
> +
> + for (i = 0; i < l; i++) {
> + if (!(m[i] = calloc(l, sizeof(int))))
> + break;
> + }
> + if (i != l)
> + break;
> +
> + return m;
> + } while(0);
Maybe just m = calloc(l*l, sizeof(int))?
> +
> + OSM_LOG(p_log, OSM_LOG_ERROR, "Failed allocating matrix - out of
> memory\n");
> +
> + m_free(m, l);
> + return NULL;
> +}
> +
> +/*
> + * pm_free
> + *
> + * free a square matrix of rank l of polynomials
> + */
> +static void pm_free(int ***m, int l)
> +{
> + int i, j;
> +
> + if (m) {
> + for (i = 0; i < l; i++) {
> + if (m[i]) {
> + for (j = 0; j < l; j++) {
> + if (m[i][j])
> + free(m[i][j]);
> + }
> + free(m[i]);
> + }
> + }
> + free(m);
> + }
> +}
> +
> +/*
> + * pm_alloc
> + *
> + * allocate a square matrix of rank l of polynomials of degree n
> + */
> +static int ***pm_alloc(lash_t *p_lash, int l, int n)
> +{
> + osm_log_t *p_log = &p_lash->p_osm->log;
> + int i, j;
> + int ***m = NULL;
> +
> + do {
> + if (!(m = calloc(l, sizeof(int **))))
> + break;
> +
> + for (i = 0; i < l; i++) {
> + if (!(m[i] = calloc(l, sizeof(int *))))
> + break;
> +
> + for (j = 0; j < l; j++) {
> + if (!(m[i][j] = calloc(n+1, sizeof(int))))
> + break;
> + }
> + if (j != l)
> + break;
> + }
> + if (i != l)
> + break;
> +
> + return m;
> + } while(0);
Ditto.
> +
> + OSM_LOG(p_log, OSM_LOG_ERROR, "Failed allocating matrix - out of
> memory\n");
> +
> + pm_free(m, l);
> + return NULL;
> +}
> +
> +static int determinant(lash_t *p_lash, int n, int rank, int ***m, int *p);
> +
> +/*
> + * sub_determinant
> + *
> + * compute the determinant of a submatrix of matrix of rank l of
> polynomials of degree n
> + * with row and col removed in poly. caller must free poly
> + */
> +static int sub_determinant(lash_t *p_lash, int n, int l, int row, int col,
> int ***matrix, int **poly)
> +{
> + int ret = -1;
> + int ***m = NULL;
> + int *p = NULL;
> + int i, j, k, x, y;
> + int rank = l - 1;
> +
> + do {
> + if (!(p = poly_alloc(p_lash, n))) {
> + break;
> + }
> +
> + if (rank <= 0) {
> + p[0] = 1;
> + ret = 0;
> + break;
> + }
> +
> + if (!(m = pm_alloc(p_lash, rank, n))) {
> + free(p);
> + p = NULL;
> + break;
> + }
> +
> + x = 0;
> + for (i = 0; i < l; i++) {
> + if (i == row)
> + continue;
> +
> + y = 0;
> + for (j = 0; j < l; j++) {
> + if (j == col)
> + continue;
> +
> + for (k = 0; k <= n; k++)
> + m[x][y][k] = matrix[i][j][k];
> +
> + y++;
> + }
> + x++;
> + }
> +
> + if (determinant(p_lash, n, rank, m, p)) {
> + free(p);
> + p = NULL;
> + break;
> + }
> +
> + ret = 0;
> + } while(0);
> +
> + pm_free(m, rank);
> + *poly = p;
> + return ret;
> +}
> +
> +/*
> + * determinant
> + *
> + * compute the determinant of matrix m of rank of polynomials of degree deg
> + * and add the result to polynomial p allocated by caller
> + */
> +static int determinant(lash_t *p_lash, int deg, int rank, int ***m, int *p)
> +{
> + int i, j, k;
> + int *q;
> + int sign = 1;
> +
> + /*
> + * handle simple case of 1x1 matrix
> + */
> + if (rank == 1) {
> + for (i = 0; i <= deg; i++)
> + p[i] += m[0][0][i];
> + }
> +
> + /*
> + * handle simple case of 2x2 matrix
> + */
> + else if (rank == 2) {
> + for (i = 0; i <= deg; i++) {
> + if (m[0][0][i] == 0)
> + continue;
> +
> + for (j = 0; j <= deg; j++) {
> + if (m[1][1][j] == 0)
> + continue;
> +
> + p[i+j] += m[0][0][i]*m[1][1][j];
> + }
> + }
> +
> + for (i = 0; i <= deg; i++) {
> + if (m[0][1][i] == 0)
> + continue;
> +
> + for (j = 0; j <= deg; j++) {
> + if (m[1][0][j] == 0)
> + continue;
> +
> + p[i+j] -= m[0][1][i]*m[1][0][j];
> + }
> + }
> + }
> +
> + /*
> + * handle the general case
> + */
> + else {
> + for (i = 0; i < rank; i++) {
> + if (sub_determinant(p_lash, deg, rank, 0, i, m, &q))
> + return -1;
> +
> + for (j = 0; j <= deg; j++) {
> + if (m[0][i][j] == 0)
> + continue;
> +
> + for (k = 0; k <= deg; k++) {
> + if (q[k] == 0)
> + continue;
> +
> + p[j+k] += sign*m[0][i][j]*q[k];
> + }
> + }
> +
> + free(q);
> + sign = -sign;
> + }
> + }
> +
> + return 0;
> +}
> +
> +/*
> * osm_mesh_cleanup - free per mesh resources
> */
> void osm_mesh_cleanup(lash_t *p_lash)
>
>
More information about the general
mailing list