[net.sources.bugs] Retraction

chris@umcp-cs.UUCP (Chris Torek) (11/20/85)

Your routine may not work on machines with severe alignment
constraints.  More important, however, is your use of `valloc'.
`valloc'ed memory is page aligned, normally only used in cases
where a virtual memory system wants to move it around by changing
PTEs rather than by copying; moreover, this memory cannot be given
back on a standard system (I consider this a bug in valloc, but it
is there.)

Here is a `portable' matrix allocator that uses `malloc', along
with a matrix destroyer.  The remaining routines are left as an
exercise to the reader....

/*
 * matalloc.c - matrix allocation and freeing routines.
 */

#define	NULL	0		/* standard, portable, and correct! */

char	*malloc();		/* eventually `char *malloc(int n);' */
void	free();			/* eventually `void free(char *p);' */

/*
 * This type belongs in mat.h, but I am creating this on the fly
 * and want a self-contained example.  Separate this out before
 * using these routines in `real live code'.
 */
typedef struct matrix {
	int	m_rows;		/* number of rows */
	int	m_cols;		/* number of columns */
	double	**m_data;	/* the base of the row set */
} MATRIX;

/*
 * Create a matrix of size `rows' by `cols', and initialize
 * it to contain all `init' values.  Return a pointer to the
 * new matrix, or NULL for failure.
 */
MATRIX *
mat_alloc(rows, cols, init)
	int rows, cols;
	double init;
{
	register int j, i;
	register double *cp, **rp;
	register MATRIX *m;

	/*
	 * Allocate the matrix descriptor.
	 */
	if ((m = (MATRIX *)malloc(sizeof *m)) == NULL)
		return (NULL);

	/*
	 * Allocate the row vector.
	 */
	if ((rp = (double **)malloc(rows * sizeof (double *))) == NULL) {
		free((char *)m);
		return (NULL);
	}
	m->m_data = rp;

	/*
	 * Allocate each of the column vectors.  It is safe to allocate
	 * one large array now and break it up into pieces; indeed, this
	 * uses less memory and makes error recovery simpler here.
	 *
	 * (Pardon my `count down to zero' style; I use it when only the
	 * number of trips through the loop is of interest, not the index
	 * itself.  It generates better code on many machines....)
	 */
	if ((cp = (double *)malloc(rows * cols * sizeof (double))) == NULL) {
		free((char *)rp);
		free((char *)m);
		return (NULL);
	}
	for (i = rows; --i >= 0;) {
		*rp++ = cp;		/* record position of this column */
		for (j = cols; --j >= 0;)
			*cp++ = init;	/* and initialize it */
	}
	return (m);
}

/*
 * Free the matrix `m'.
 */
void
mat_free(m)
	register MATRIX *m;
{

	free((char *)*m->m_data);	/* free the column array */
	free((char *)m->m_data);	/* and the row vector */
	free((char *)m);		/* and finally the descriptor */
}
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 4251)
UUCP:	seismo!umcp-cs!chris
CSNet:	chris@umcp-cs		ARPA:	chris@mimsy.umd.edu

roy@phri.UUCP (Roy Smith) (11/21/85)

> Here is a `portable' matrix allocator that uses `malloc', along
> with a matrix destroyer.  The remaining routines are left as an
> exercise to the reader....

	Take a look at mod.sources Vol 2, No. 36 for a similar set of
routines I wrote, along with an description of how vectored arrays work,
and why they are different from 2-d arrays.  My stuff doesn't allow for
initialization (easy enough to add, I guess), but it does allow for
arbitrary sized array elements.  If you don't have the archives, contact me
direct for a copy.
-- 
Roy Smith <allegra!phri!roy>
System Administrator, Public Health Research Institute
455 First Avenue, New York, NY 10016