/*-=-=-=-=-=-=-=-=-=-=-=- RCCL/RCI Notice of Copyright -=-=-=-=-=-=-=-=-=-=-*
 *									    *
 *	Copyright (C) 1987, 1991 by John E. Lloyd.			    *
 *									    *
 *	Information on copyright permissions, as well as a complete	    *
 *	disclaimer of warranty, is given in the file COPYRIGHT.		    *
 *									    *
 *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/

/*=~=~=~=~ McGill-Computer-Vision-and-Robotics-Laboratory--C-Module ~=~=~=~=
 *		
 * MODULE NAME:	matrixAlloc
 *
 * DESCRIPTION:	Routines to initialize and allocate matrix data structures.
 * 
 * AUTHOR/DATE:	John Lloyd, Summer 1987.
 *
 *~=~=~=~=~=~= McGill-Computer-Vision-and-Robotics-Laboratory ~=~=~=~=~=~=*/

#include "cdefs.h"
#include "types.h"
#include "error.h"

/* Allocate memory for a matrix and initialize the row-column information.
   The memory is allocated using malloc. This should be used for 
   'permanent' allocation such as symbol table information. The matrix
   can be freed with a call to free */

matrix *malloc_matrix (row, col)
int row, col;
{
	matrix *m;

	m = (matrix *)malloc (sizeof(matrix) + row*col*sizeof(double));
	if (m == NULL)
	 { error (0, "cannot allocate matrix -- out of space\n");
	   return (NULL);
	 }
	m->row = row;
	m->col = col;
	m->buf = (double *)((char *)m + sizeof(matrix));
	return (m);
}

/* Same as malloc_matrix(), except that the memory is derived from 
   the temporay talloc() storage. Items obtained from this store
   should not be freed explicitly; the freeing is done all at once
   at specific execution points using talloc_reset() */

matrix *talloc_matrix (row, col)
int row, col;
{
	matrix *m;

	m = (matrix *)talloc (sizeof(matrix) + row*col*sizeof(double));
	if (m == NULL)
	 { error (0, "cannot allocate matrix -- out of space\n");
	   return (NULL);
	 }
	m->row = row;
	m->col = col;
	m->buf = (double *)((char *)m + sizeof(matrix));
	return (m);
}

/* Copy a matrix using malloc_matrix() */

matrix *mcopy_matrix (m1)
matrix *m1;
{
	matrix *mr;
	int i, j;

	if ((mr = malloc_matrix (m1->row, m1->col)) == NULL)
	 { return (NULL);
	 }
 	for (i=0; i<m1->row; i++)
 	 { for (j=0; j<m1->col; j++)
	    { mr->buf[i*mr->col+j] = m1->buf[i*m1->col+j];
	    }
	 }
	return (mr);
}

/* Copy a matrix using talloc_matrix() */

matrix *tcopy_matrix (m1)
matrix *m1;
{
	matrix *mr;
	int i, j;

	if ((mr = talloc_matrix (m1->row, m1->col)) == NULL)
	 { return (NULL);
	 }
 	for (i=0; i<m1->row; i++)
 	 { for (j=0; j<m1->col; j++)
	    { mr->buf[i*mr->col+j] = m1->buf[i*m1->col+j];
	    }
	 }
	return (mr);
}

/* Convert a double to it's equivalent matrix. Allocate the space
   using malloc_matrix() */

matrix *mdouble_to_matrix (d)
double d;
{
	matrix *r;

	if ((r = malloc_matrix (1,1)) == NULL)
	 { return (NULL);
	 }
 	else
	 { r->buf[0] = d;
	 }
	return (r);
}

/* Same as mdouble_to_matrix(), only uses talloc_matrix() instead */

matrix *tdouble_to_matrix (d)
double d;
{
	matrix *r;

	if ((r = talloc_matrix (1,1)) == NULL)
	 { return (NULL);
	 }
 	else
	 { r->buf[0] = d;
	 }
	return (r);
}
