[ofa-general] [PATCH][4] opensm: vector and matrix utilities

Robert Pearson rpearson at systemfabricworks.com
Tue Nov 11 08:44:50 PST 2008


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;
+	}
+
+	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);
+
+	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);
+
+	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