/*===========================================================================
  Copyright (C) 2001 European Southern Observatory (ESO)
 
  This program is free software; you can redistribute it and/or 
  modify it under the terms of the GNU General Public License as 
  published by the Free Software Foundation; either version 2 of 
  the License, or (at your option) any later version.
 
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
 
  You should have received a copy of the GNU General Public 
  License along with this program; if not, write to the Free 
  Software Foundation, Inc., 675 Massachusetss Ave, Cambridge, 
  MA 02139, USA.
 
  Corresponding concerning ESO-MIDAS should be addressed as follows:
    Internet e-mail: midas@eso.org
    Postal address: European Southern Observatory
            Data Management Division 
            Karl-Schwarzschild-Strasse 2
            D 85748 Garching bei Muenchen 
            GERMANY
===========================================================================*/
/* Program  : newmatrix.c                                                  */
/* Author   : G. Mulas  -  ITAL_FLAMES Consortium (derived by NR)          */
/* Date     :                                                              */
/*                                                                         */
/* Purpose  : Missing                                                      */
/*                                                                         */
/*                                                                         */
/* Input:  see interface                                                   */ 
/*                                                                      */
/* Output:                                                              */
/*                                                                         */
/* DRS Functions called:                                                   */
/* none                                                                    */ 
/*                                                                         */ 
/* Pseudocode:                                                             */
/* Missing                                                                 */ 
/*                                                                         */ 
/* Version  :                                                              */
/* Last modification date: 2002/08/05                                      */
/* Who     When        Why                Where                            */
/* AMo     02-08-05   Add header         header                            */
/*-------------------------------------------------------------------------*/

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif


#if defined(__STDC__) || defined(ANSI) || defined(NRANSI) /* ANSI */

#include <flames_newmatrix.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <flames_midas_def.h>
#include <flames_uves.h>
#include <uves_error.h>
#define NR_END 1
#define FREE_ARG char*

//jmlarsen: Maybe we should respect the fine people at NR and
//          *not* steal their copyrighted code???


void  nrerror(const char* error_text)
/* Numerical Recipes standard error handler */

{
  /*
    ---------- Let's comment out the non-MIDAS compliant items----------
 
    fprintf(stderr,"Numerical Recipes run-time error...\n");
    fprintf(stderr,"%s\n",error_text);
    fprintf(stderr,"...now exiting to system...\n");
  */    
  char output[70];
 
  SCTPUT("Numerical Recipes run-time error...\n"); 
  sprintf(output, "%s\n", error_text);
  SCTPUT(output); 
  SCTPUT("...now exiting to system...\n"); 
  SCSEPI();

  //UVES error handling here
  assure_nomsg( false, CPL_ERROR_ILLEGAL_OUTPUT );
 cleanup:
  return ;
}

float *vector(int32_t nl, int32_t nh)
/* allocate a float vector with subscript range v[nl..nh] */
{
  float *v;

  v=(float *) calloc((size_t) (nh-nl+1+NR_END), sizeof(float));
  if (!v) {
     nrerror("allocation failure in vector()");
     free(v);
     return NULL;
  } else {
     return v-nl+NR_END;
  }
}

int *ivector(int32_t nl, int32_t nh)
/* allocate an int vector with subscript range v[nl..nh] */
{
  int *v;

  v=(int *) calloc((size_t) (nh-nl+1+NR_END), sizeof(int));
  if (!v) {
	  nrerror("allocation failure in ivector()");
	  free(v);
	  return NULL;
  } else {
      return v-nl+NR_END;
  }
}

unsigned int *uivector(int32_t nl, int32_t nh)
/* allocate an unsigned int vector with subscript range v[nl..nh] */
{
  unsigned int *v;

  v=(unsigned int *) calloc((size_t) (nh-nl+1+NR_END), 
			    sizeof(unsigned int));
  if (!v) {
	  nrerror("allocation failure in uivector()");
	  free(v);
	  return NULL;
  } else {
      return v-nl+NR_END;
  }
}

char *cvector(int32_t nl, int32_t nh)
/* allocate a char vector with subscript range v[nl..nh] */
{
  char *v;

  v=(char *) calloc((size_t) (nh-nl+1+NR_END), sizeof(char));
  if (!v) {
	  nrerror("allocation failure in cvector()");
	  free(v);
	  return NULL;
  } else {
      return v-nl+NR_END;
  }
}

unsigned char *ucvector(int32_t nl, int32_t nh)
/* allocate an unsigned char vector with subscript range v[nl..nh] */
{
  unsigned char *v;

  v=(unsigned char *) calloc((size_t) (nh-nl+1+NR_END), 
			     sizeof(unsigned char));
  if (!v) {
	  nrerror("allocation failure in ucvector()");
	  free(v);
	  return NULL;
  } else {
      return v-nl+NR_END;
  }
}

int32_t *lvector(int32_t nl, int32_t nh)
/* allocate a int32_t vector with subscript range v[nl..nh] */
{
  int32_t *v;

  v=(int32_t *) calloc((size_t) (nh-nl+1+NR_END), sizeof(int32_t));
  if (!v) {
	  nrerror("allocation failure in lvector()");
	  free(v);
	  return NULL;
  } else {
      return v-nl+NR_END;
  }
}

uint32_t *ulvector(int32_t nl, int32_t nh)
/* allocate an uint32_t vector with subscript range v[nl..nh] */
{
  uint32_t *v;

  v=(uint32_t *) calloc((size_t) (nh-nl+1+NR_END), 
			     sizeof(uint32_t));
  if (!v) {
	  nrerror("allocation failure in ulvector()");
	  free(v);
	  return NULL;
  } else {
      return v-nl+NR_END;
  }
}

double *dvector(int32_t nl, int32_t nh)
/* allocate a double vector with subscript range v[nl..nh] */
{
  double *v;

  v=(double *) calloc((size_t) (nh-nl+1+NR_END), sizeof(double));
  if (!v) {
	  nrerror("allocation failure in dvector()");
	  free(v);
	  return NULL;
  } else {
      return v-nl+NR_END;
  }
}

frame_data *fdvector(int32_t nl, int32_t nh)
/* allocate a frame_data vector with subscript range v[nl..nh] */
{
  frame_data *v;

  v=(frame_data *) calloc((size_t) (nh-nl+1+NR_END), sizeof(frame_data));
  if (!v) {
	  nrerror("allocation failure in fdvector()");
	  free(v);
	  return NULL;
  } else {
      return v-nl+NR_END;
  }
}

frame_mask *fmvector(int32_t nl, int32_t nh)
/* allocate a frame_mask vector with subscript range v[nl..nh] */
{
  frame_mask *v;

  v=(frame_mask *) calloc((size_t) (nh-nl+1+NR_END), sizeof(frame_mask));
  if (!v) {
	  nrerror("allocation failure in fdvector()");
	  free(v);
	  return NULL;
  } else {
      return v-nl+NR_END;
  }
}

char **cmatrix(int32_t nrl, int32_t nrh, int32_t ncl, int32_t nch)
/* allocate a char matrix with subscript range m[nrl..nrh][ncl..nch] */
{
  int32_t i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
  char **m;

  /* allocate pointers to rows */
  m=(char **) calloc((size_t)(nrow+NR_END), sizeof(char*));
  if (!m) nrerror("allocation failure 1 in cmatrix()");
  m += NR_END;
  m -= nrl;

  /* allocate rows and set pointers to them */
  m[nrl]=(char *) calloc((size_t)(nrow*ncol+NR_END), sizeof(char));
  if (!m[nrl]) nrerror("allocation failure 2 in cmatrix()");
  m[nrl] += NR_END;
  m[nrl] -= ncl;

  for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol;

  /* return pointer to array of pointers to rows */
  return m;
}

float **matrix(int32_t nrl, int32_t nrh, int32_t ncl, int32_t nch)
/* allocate a float matrix with subscript range m[nrl..nrh][ncl..nch] */
{
  int32_t i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
  float **m;

  /* allocate pointers to rows */
  m=(float **) calloc((size_t)(nrow+NR_END), sizeof(float*));
  if (!m) nrerror("allocation failure 1 in matrix()");
  m += NR_END;
  m -= nrl;

  /* allocate rows and set pointers to them */
  m[nrl]=(float *) calloc((size_t)(nrow*ncol+NR_END), sizeof(float));
  if (!m[nrl]) nrerror("allocation failure 2 in matrix()");
  m[nrl] += NR_END;
  m[nrl] -= ncl;

  for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol;

  /* return pointer to array of pointers to rows */
  return m;
}

double **dmatrix(int32_t nrl, int32_t nrh, int32_t ncl, int32_t nch)
/* allocate a double matrix with subscript range m[nrl..nrh][ncl..nch] */
{
  int32_t i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
  double **m;

  /* allocate pointers to rows */
  m=(double **) calloc((size_t)(nrow+NR_END), sizeof(double*));
  if (!m) nrerror("allocation failure 1 in dmatrix()");
  m += NR_END;
  m -= nrl;
   

  /* allocate rows and set pointers to them */
  /*
    printf("nrl=%d\n",nrl);
    printf("size=%d\n",nrow*ncol+NR_END);
  */
  m[nrl]=(double *) calloc((size_t)(nrow*ncol+NR_END), sizeof(double));

  /* printf("allocate pointers to rows4\n"); */
  if (!m[nrl]) nrerror("allocation failure 2 in dmatrix()");
  m[nrl] += NR_END;
  m[nrl] -= ncl;

  for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol;
  /* return pointer to array of pointers to rows */
  return m;
}

int **imatrix(int32_t nrl, int32_t nrh, int32_t ncl, int32_t nch)
/* allocate a int matrix with subscript range m[nrl..nrh][ncl..nch] */
{
  int32_t i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
  int **m;

  /* allocate pointers to rows */
  m=(int **) calloc((size_t)(nrow+NR_END), sizeof(int*));
  if (!m) nrerror("allocation failure 1 in imatrix()");
  m += NR_END;
  m -= nrl;


  /* allocate rows and set pointers to them */
  m[nrl]=(int *) calloc((size_t)(nrow*ncol+NR_END), sizeof(int));
  if (!m[nrl]) nrerror("allocation failure 2 in imatrix()");
  m[nrl] += NR_END;
  m[nrl] -= ncl;

  for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol;

  /* return pointer to array of pointers to rows */
  return m;
}

uint32_t **ulmatrix(int32_t nrl, int32_t nrh, int32_t ncl, int32_t nch)
/* allocate a int matrix with subscript range m[nrl..nrh][ncl..nch] */
{
  int32_t i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
  uint32_t **m;

  /* allocate pointers to rows */
  m=(uint32_t **) calloc((size_t)(nrow+NR_END), 
				  sizeof(uint32_t*));
  if (!m) nrerror("allocation failure 1 in ulmatrix()");
  m += NR_END;
  m -= nrl;


  /* allocate rows and set pointers to them */
  m[nrl]=(uint32_t *) calloc((size_t)(nrow*ncol+NR_END), 
				      sizeof(uint32_t));
  if (!m[nrl]) nrerror("allocation failure 2 in ulmatrix()");
  m[nrl] += NR_END;
  m[nrl] -= ncl;

  for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol;

  /* return pointer to array of pointers to rows */
  return m;
}

int32_t **lmatrix(int32_t nrl, int32_t nrh, int32_t ncl, int32_t nch)
/* allocate a int32_t matrix with subscript range m[nrl..nrh][ncl..nch] */
{
  int32_t i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
  int32_t **m;

  /* allocate pointers to rows */
  m=(int32_t **) calloc((size_t)(nrow+NR_END), sizeof(int32_t*));
  if (!m) nrerror("allocation failure 1 in lmatrix()");
  m += NR_END;
  m -= nrl;


  /* allocate rows and set pointers to them */
  m[nrl]=(int32_t *) calloc((size_t)(nrow*ncol+NR_END), 
			     sizeof(int32_t));
  if (!m[nrl]) nrerror("allocation failure 2 in lmatrix()");
  m[nrl] += NR_END;
  m[nrl] -= ncl;

  for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol;

  /* return pointer to array of pointers to rows */
  return m;
}

frame_data **fdmatrix(int32_t nrl, int32_t nrh, int32_t ncl, int32_t nch)
/* allocate a frame_data matrix with subscript range m[nrl..nrh][ncl..nch] */
{
  int32_t i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
  frame_data **m;

  /* allocate pointers to rows */
  m=(frame_data **) calloc((size_t)(nrow+NR_END), sizeof(frame_data*));
  if (!m) nrerror("allocation failure 1 in fdmatrix()");
  m += NR_END;
  m -= nrl;


  /* allocate rows and set pointers to them */
  m[nrl]=(frame_data *) calloc((size_t)(nrow*ncol+NR_END), 
			       sizeof(frame_data));
  if (!m[nrl]) nrerror("allocation failure 2 in fdmatrix()");
  m[nrl] += NR_END;
  m[nrl] -= ncl;

  for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol;

  /* return pointer to array of pointers to rows */
  return m;
}

frame_mask **fmmatrix(int32_t nrl, int32_t nrh, int32_t ncl, int32_t nch)
/* allocate a frame_mask matrix with subscript range m[nrl..nrh][ncl..nch] */
{
  int32_t i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
  frame_mask **m;

  /* allocate pointers to rows */
  m=(frame_mask **) calloc((size_t)(nrow+NR_END), sizeof(frame_mask*));
  if (!m) nrerror("allocation failure 1 in fmmatrix()");
  m += NR_END;
  m -= nrl;


  /* allocate rows and set pointers to them */
  m[nrl]=(frame_mask *) calloc((size_t)(nrow*ncol+NR_END), 
			       sizeof(frame_mask));
  if (!m[nrl]) nrerror("allocation failure 2 in fmmatrix()");
  m[nrl] += NR_END;
  m[nrl] -= ncl;

  for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol;

  /* return pointer to array of pointers to rows */
  return m;
}

float **submatrix(float **a, int32_t oldrl, int32_t oldrh, int32_t oldcl,
		  int32_t newrl, int32_t newcl)
/* point a submatrix [newrl..][newcl..] to a[oldrl..oldrh][oldcl..oldch] */
{
  int32_t i,j,nrow=oldrh-oldrl+1,ncol=oldcl-newcl;
  float **m;

  /* allocate array of pointers to rows */
  m=(float **) calloc((size_t) (nrow+NR_END), sizeof(float*));
  if (!m) nrerror("allocation failure in submatrix()");
  m += NR_END;
  m -= newrl;

  /* set pointers to rows */
  for(i=oldrl,j=newrl;i<=oldrh;i++,j++) m[j]=a[i]+ncol;

  /* return pointer to array of pointers to rows */
  return m;
}

float **convert_matrix(float *a, int32_t nrl, int32_t nrh, int32_t ncl, int32_t nch)
/* allocate a float matrix m[nrl..nrh][ncl..nch] that points to the matrix
   declared in the standard C manner as a[nrow][ncol], where nrow=nrh-nrl+1
   and ncol=nch-ncl+1. The routine should be called with the address
   &a[0][0] as the first argument. */
{
  int32_t i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1;
  float **m;

  /* allocate pointers to rows */
  m=(float **) calloc((size_t) (nrow+NR_END), sizeof(float*));
  if (!m) nrerror("allocation failure in convert_matrix()");
  m += NR_END;
  m -= nrl;

  /* set pointers to rows */
  m[nrl]=a-ncl;
  for(i=1,j=nrl+1;i<nrow;i++,j++) m[j]=m[j-1]+ncol;
  /* return pointer to array of pointers to rows */
  return m;
}

float ***f3tensor(int32_t nrl, int32_t nrh, int32_t ncl, int32_t nch, int32_t ndl, int32_t ndh)
/* allocate a float 3tensor with range t[nrl..nrh][ncl..nch][ndl..ndh] */
{
  int32_t i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1,ndep=ndh-ndl+1;
  float ***t;

  /* allocate pointers to pointers to rows */
  t=(float ***) calloc((size_t)(nrow+NR_END), sizeof(float**));
  if (!t) nrerror("allocation failure 1 in f3tensor()");
  t += NR_END;
  t -= nrl;

  /* allocate pointers to rows and set pointers to them */
  t[nrl]=(float **) calloc((size_t)(nrow*ncol+NR_END), sizeof(float*));
  if (!t[nrl]) nrerror("allocation failure 2 in f3tensor()");
  t[nrl] += NR_END;
  t[nrl] -= ncl;

  /* allocate rows and set pointers to them */
  t[nrl][ncl]=(float *) calloc((size_t)(nrow*ncol*ndep+NR_END), 
			       sizeof(float));
  if (!t[nrl][ncl]) nrerror("allocation failure 3 in f3tensor()");
  t[nrl][ncl] += NR_END;
  t[nrl][ncl] -= ndl;

  for(j=ncl+1;j<=nch;j++) t[nrl][j]=t[nrl][j-1]+ndep;
  for(i=nrl+1;i<=nrh;i++) {
    t[i]=t[i-1]+ncol;
    t[i][ncl]=t[i-1][ncl]+ncol*ndep;
    for(j=ncl+1;j<=nch;j++) t[i][j]=t[i][j-1]+ndep;
  }

  /* return pointer to array of pointers to rows */
  return t;
}

double ***d3tensor(int32_t nrl, int32_t nrh, int32_t ncl, int32_t nch, int32_t ndl, int32_t ndh)
/* allocate a float 3tensor with range t[nrl..nrh][ncl..nch][ndl..ndh] */
{
  int32_t i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1,ndep=ndh-ndl+1;
  double ***t;

  /* allocate pointers to pointers to rows */
  t=(double ***) calloc((size_t)(nrow+NR_END), sizeof(double**));
  if (!t) nrerror("allocation failure 1 in d3tensor()");
  t += NR_END;
  t -= nrl;

  /* allocate pointers to rows and set pointers to them */
  t[nrl]=(double **) calloc((size_t)(nrow*ncol+NR_END), sizeof(double*));
  if (!t[nrl]) nrerror("allocation failure 2 in d3tensor()");
  t[nrl] += NR_END;
  t[nrl] -= ncl;

  /* allocate rows and set pointers to them */
  t[nrl][ncl]=(double *) calloc((size_t)(nrow*ncol*ndep+NR_END), 
				sizeof(double));
  if (!t[nrl][ncl]) nrerror("allocation failure 3 in d3tensor()");
  t[nrl][ncl] += NR_END;
  t[nrl][ncl] -= ndl;

  for(j=ncl+1;j<=nch;j++) t[nrl][j]=t[nrl][j-1]+ndep;
  for(i=nrl+1;i<=nrh;i++) {
    t[i]=t[i-1]+ncol;
    t[i][ncl]=t[i-1][ncl]+ncol*ndep;
    for(j=ncl+1;j<=nch;j++) t[i][j]=t[i][j-1]+ndep;
  }

  /* return pointer to array of pointers to rows */
  return t;
}

frame_data ***fd3tensor(int32_t nrl, int32_t nrh, int32_t ncl, int32_t nch, int32_t ndl, int32_t ndh)
/* allocate a frame_data 3tensor with range t[nrl..nrh][ncl..nch][ndl..ndh] */
{
  int32_t i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1,ndep=ndh-ndl+1;
  frame_data ***t;

  /* allocate pointers to pointers to rows */
  t=(frame_data ***) calloc((size_t)(nrow+NR_END), sizeof(frame_data**));
  if (!t) nrerror("allocation failure 1 in fd3tensor()");
  t += NR_END;
  t -= nrl;

  /* allocate pointers to rows and set pointers to them */
  t[nrl]=(frame_data **) calloc((size_t)(nrow*ncol+NR_END), 
				sizeof(frame_data*));
  if (!t[nrl]) nrerror("allocation failure 2 in fd3tensor()");
  t[nrl] += NR_END;
  t[nrl] -= ncl;

  /* allocate rows and set pointers to them */
  t[nrl][ncl]=(frame_data *) calloc((size_t)(nrow*ncol*ndep+NR_END), 
				    sizeof(frame_data));
  if (!t[nrl][ncl]) nrerror("allocation failure 3 in fd3tensor()");
  t[nrl][ncl] += NR_END;
  t[nrl][ncl] -= ndl;

  for(j=ncl+1;j<=nch;j++) t[nrl][j]=t[nrl][j-1]+ndep;
  for(i=nrl+1;i<=nrh;i++) {
    t[i]=t[i-1]+ncol;
    t[i][ncl]=t[i-1][ncl]+ncol*ndep;
    for(j=ncl+1;j<=nch;j++) t[i][j]=t[i][j-1]+ndep;
  }

  /* return pointer to array of pointers to rows */
  return t;
}

frame_mask ***fm3tensor(int32_t nrl, int32_t nrh, int32_t ncl, int32_t nch, int32_t ndl, int32_t ndh)
/* allocate a frame_mask 3tensor with range t[nrl..nrh][ncl..nch][ndl..ndh] */
{
  int32_t i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1,ndep=ndh-ndl+1;
  frame_mask ***t;

  /* allocate pointers to pointers to rows */
  t=(frame_mask ***) calloc((size_t)(nrow+NR_END), sizeof(frame_mask**));
  if (!t) nrerror("allocation failure 1 in f3tensor()");
  t += NR_END;
  t -= nrl;

  /* allocate pointers to rows and set pointers to them */
  t[nrl]=(frame_mask **) calloc((size_t)(nrow*ncol+NR_END), 
				sizeof(frame_mask*));
  if (!t[nrl]) nrerror("allocation failure 2 in f3tensor()");
  t[nrl] += NR_END;
  t[nrl] -= ncl;

  /* allocate rows and set pointers to them */
  t[nrl][ncl]=(frame_mask *) calloc((size_t)(nrow*ncol*ndep+NR_END), 
				    sizeof(frame_mask));
  if (!t[nrl][ncl]) nrerror("allocation failure 3 in f3tensor()");
  t[nrl][ncl] += NR_END;
  t[nrl][ncl] -= ndl;

  for(j=ncl+1;j<=nch;j++) t[nrl][j]=t[nrl][j-1]+ndep;
  for(i=nrl+1;i<=nrh;i++) {
    t[i]=t[i-1]+ncol;
    t[i][ncl]=t[i-1][ncl]+ncol*ndep;
    for(j=ncl+1;j<=nch;j++) t[i][j]=t[i][j-1]+ndep;
  }

  /* return pointer to array of pointers to rows */
  return t;
}

uint32_t ***ul3tensor(int32_t nrl, int32_t nrh, int32_t ncl, int32_t nch, int32_t ndl, int32_t ndh)
/* allocate a frame_mask 3tensor with range t[nrl..nrh][ncl..nch][ndl..ndh] */
{
  int32_t i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1,ndep=ndh-ndl+1;
  uint32_t ***t;

  /* allocate pointers to pointers to rows */
  t=(uint32_t ***) calloc((size_t)(nrow+NR_END), 
				   sizeof(uint32_t**));
  if (!t) nrerror("allocation failure 1 in f3tensor()");
  t += NR_END;
  t -= nrl;

  /* allocate pointers to rows and set pointers to them */
  t[nrl]=(uint32_t **) calloc((size_t)(nrow*ncol+NR_END), 
				       sizeof(uint32_t*));
  if (!t[nrl]) nrerror("allocation failure 2 in f3tensor()");
  t[nrl] += NR_END;
  t[nrl] -= ncl;

  /* allocate rows and set pointers to them */
  t[nrl][ncl]=
    (uint32_t *) calloc((size_t)(nrow*ncol*ndep+NR_END), 
				 sizeof(uint32_t));
  if (!t[nrl][ncl]) nrerror("allocation failure 3 in f3tensor()");
  t[nrl][ncl] += NR_END;
  t[nrl][ncl] -= ndl;

  for(j=ncl+1;j<=nch;j++) t[nrl][j]=t[nrl][j-1]+ndep;
  for(i=nrl+1;i<=nrh;i++) {
    t[i]=t[i-1]+ncol;
    t[i][ncl]=t[i-1][ncl]+ncol*ndep;
    for(j=ncl+1;j<=nch;j++) t[i][j]=t[i][j-1]+ndep;
  }

  /* return pointer to array of pointers to rows */
  return t;
}

int32_t ***l3tensor(int32_t nrl, int32_t nrh, int32_t ncl, int32_t nch, int32_t ndl, int32_t ndh)
/* allocate a int32_t 3tensor with range t[nrl..nrh][ncl..nch][ndl..ndh] */
{
  int32_t i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1,ndep=ndh-ndl+1;
  int32_t ***t;

  /* allocate pointers to pointers to rows */
  t=(int32_t ***) calloc((size_t)(nrow+NR_END), sizeof(int32_t**));
  if (!t) nrerror("allocation failure 1 in f3tensor()");
  t += NR_END;
  t -= nrl;

  /* allocate pointers to rows and set pointers to them */
  t[nrl]=(int32_t **) calloc((size_t)(nrow*ncol+NR_END), 
			      sizeof(int32_t*));
  if (!t[nrl]) nrerror("allocation failure 2 in f3tensor()");
  t[nrl] += NR_END;
  t[nrl] -= ncl;

  /* allocate rows and set pointers to them */
  t[nrl][ncl]=(int32_t *) calloc((size_t)(nrow*ncol*ndep+NR_END), 
				  sizeof(int32_t));
  if (!t[nrl][ncl]) nrerror("allocation failure 3 in f3tensor()");
  t[nrl][ncl] += NR_END;
  t[nrl][ncl] -= ndl;

  for(j=ncl+1;j<=nch;j++) t[nrl][j]=t[nrl][j-1]+ndep;
  for(i=nrl+1;i<=nrh;i++) {
    t[i]=t[i-1]+ncol;
    t[i][ncl]=t[i-1][ncl]+ncol*ndep;
    for(j=ncl+1;j<=nch;j++) t[i][j]=t[i][j-1]+ndep;
  }

  /* return pointer to array of pointers to rows */
  return t;
}

int32_t ****l4tensor(int32_t nal, int32_t nah, int32_t nrl, int32_t nrh, int32_t ncl, int32_t nch, int32_t ndl, int32_t ndh)
/* allocate a int32_t 4tensor with range t[nrl..nrh][ncl..nch][ndl..ndh] */
{
  int32_t i,j,k,na=nah-nal+1,nrow=nrh-nrl+1,ncol=nch-ncl+1,ndep=ndh-ndl+1;
  int32_t ****t;

  /* allocate pointers to pointers to pointers to rows */
  t=(int32_t ****) calloc((size_t)(na+NR_END), sizeof(int32_t***));
  if (!t) nrerror("allocation failure 1 in l4tensor()");
  t += NR_END;
  t -= nal;

  /* allocate pointers to pointers to rows and set pointers to them */
  t[nal]=(int32_t ***) calloc((size_t)(na*nrow+NR_END), 
			       sizeof(int32_t**));
  if (!t[nal]) nrerror("allocation failure 2 in f3tensor()");
  t[nal] += NR_END;
  t[nal] -= nrl;

  /* allocate pointers to rows and set pointers to them */
  t[nal][nrl]=(int32_t **) calloc((size_t)(na*nrow*ncol+NR_END), 
				   sizeof(int32_t*));
  if (!t[nal][nrl]) nrerror("allocation failure 3 in f3tensor()");
  t[nal][nrl] += NR_END;
  t[nal][nrl] -= ncl;

  /* allocate rows and set pointers to them */
  t[nal][nrl][ncl]=
    (int32_t *) calloc((size_t)(na*nrow*ncol*ndep+NR_END), 
			sizeof(int32_t));
  if (!t[nal][nrl][ncl]) nrerror("allocation failure 4 in f3tensor()");
  t[nal][nrl][ncl] += NR_END;
  t[nal][nrl][ncl] -= ndl;

  for(k=ncl+1;k<=nch;k++) t[nal][nrl][k]=t[nal][nrl][k-1]+ndep;
  for(j=nrl+1;j<=nrh;j++) {
    t[nal][j] = t[nal][j-1]+ncol;
    t[nal][j][ncl] = t[nal][j-1][ncl]+ncol*ndep;
    for(k=ncl+1;k<=nch;k++) t[nal][j][k]=t[nal][j][k-1]+ndep;
  }
  for(i=nal+1;i<=nah;i++) {
    t[i]=t[i-1]+nrow;
    t[i][nrl] = t[i-1][nrl]+nrow*ncol;
    t[i][nrl][ncl] = t[i-1][nrl][ncl]+nrow*ncol*ndep;
    for(k=ncl+1;k<=nch;k++) t[i][nrl][k]=t[i][nrl][k-1]+ndep;
    for(j=nrl+1;j<=nrh;j++) {
      t[i][j] = t[i][j-1]+ncol;
      t[i][j][ncl] = t[i][j-1][ncl]+ncol*ndep;
      for(k=ncl+1;k<=nch;k++) t[i][j][k]=t[i][j][k-1]+ndep;
    }
  }

  /* return pointer to array of pointers to rows */
  return t;
}

void free_vector(float *v, int32_t nl, int32_t nh)
/* free a float vector allocated with vector() */
{
  //to remove comp warning: not used
  //nh=nh;
  free((FREE_ARG) (v+nl-NR_END));
}

void free_ivector(int *v, int32_t nl, int32_t nh)
/* free an int vector allocated with ivector() */
{
  //to remove comp warning: not used
  //nh=nh;
  free((FREE_ARG) (v+nl-NR_END));
}

void free_uivector(unsigned int *v, int32_t nl, int32_t nh)
/* free an unsigned int vector allocated with uivector() */
{
  //to remove comp warning: not used
  //nh=nh;
  free((FREE_ARG) (v+nl-NR_END));
}

void free_cvector(char *v, int32_t nl, int32_t nh)
/* free a char vector allocated with cvector() */
{
  //to remove comp warning: not used
  //nh=nh;
  free((FREE_ARG) (v+nl-NR_END));
}

void free_ucvector(unsigned char *v, int32_t nl, int32_t nh)
/* free an unsigned char vector allocated with ucvector() */
{
  //to remove comp warning: not used
  //nh=nh;
  free((FREE_ARG) (v+nl-NR_END));
}

void free_lvector(int32_t *v, int32_t nl, int32_t nh)
/* free an uint32_t vector allocated with lvector() */
{
  //to remove comp warning: not used
  //nh=nh;
  free((FREE_ARG) (v+nl-NR_END));
}

void free_ulvector(uint32_t *v, int32_t nl, int32_t nh)
/* free an uint32_t vector allocated with ulvector() */
{
  //to remove comp warning: not used
  //nh=nh;
  free((FREE_ARG) (v+nl-NR_END));
}

void free_dvector(double *v, int32_t nl, int32_t nh)
/* free a double vector allocated with dvector() */
{
  //to remove comp warning: not used
  //nh=nh;
  free((FREE_ARG) (v+nl-NR_END));
}

void free_fdvector(frame_data *v, int32_t nl, int32_t nh)
/* free a double vector allocated with dvector() */
{
  //to remove comp warning: not used
  //nh=nh;
  free((FREE_ARG) (v+nl-NR_END));
}

void free_fmvector(frame_mask *v, int32_t nl, int32_t nh)
/* free a double vector allocated with dvector() */
{
  //to remove comp warning: not used
  //nh=nh;
  free((FREE_ARG) (v+nl-NR_END));
}

void free_matrix(float **m, int32_t nrl, int32_t nrh, int32_t ncl, int32_t nch)
/* free a float matrix allocated by matrix() */
{ 
  //to remove comp warning: not used
  //nch=nch;
  //to remove comp warning: not used
  //nrh=nrh;
  free((FREE_ARG) (m[nrl]+ncl-NR_END));
  free((FREE_ARG) (m+nrl-NR_END));
}

void free_cmatrix(char **m, int32_t nrl, int32_t nrh, int32_t ncl, int32_t nch)
/* free a float matrix allocated by cmatrix() */
{
  //to remove comp warning: not used
  //nch=nch;
  //to remove comp warning: not used
  //nrh=nrh;
  free((FREE_ARG) (m[nrl]+ncl-NR_END));
  free((FREE_ARG) (m+nrl-NR_END));
}

void free_dmatrix(double **m, int32_t nrl, int32_t nrh, int32_t ncl, int32_t nch)
/* free a double matrix allocated by dmatrix() */
{
  //to remove comp warning: not used
  //nch=nch;
  //to remove comp warning: not used
  //nrh=nrh;
  free((FREE_ARG) (m[nrl]+ncl-NR_END));
  free((FREE_ARG) (m+nrl-NR_END));
}

void free_imatrix(int **m, int32_t nrl, int32_t nrh, int32_t ncl, int32_t nch)
/* free an int matrix allocated by imatrix() */
{
  //to remove comp warning: not used
  //nch=nch;
  //to remove comp warning: not used
  //nrh=nrh;
  free((FREE_ARG) (m[nrl]+ncl-NR_END));
  free((FREE_ARG) (m+nrl-NR_END));
}

void free_ulmatrix(uint32_t **m, int32_t nrl, int32_t nrh, int32_t ncl, int32_t nch)
/* free an int matrix allocated by imatrix() */
{
  //to remove comp warning: not used
  //nch=nch;
  //to remove comp warning: not used
  //nrh=nrh;
  free((FREE_ARG) (m[nrl]+ncl-NR_END));
  free((FREE_ARG) (m+nrl-NR_END));
}

void free_lmatrix(int32_t **m, int32_t nrl, int32_t nrh, int32_t ncl, int32_t nch)
/* free an int matrix allocated by imatrix() */
{
  //to remove comp warning: not used
  //nch=nch;
  //to remove comp warning: not used
  //nrh=nrh;
  free((FREE_ARG) (m[nrl]+ncl-NR_END));
  free((FREE_ARG) (m+nrl-NR_END));
}

void free_fdmatrix(frame_data **m, int32_t nrl, int32_t nrh, int32_t ncl, int32_t nch)
/* free an frame_data matrix allocated by imatrix() */
{
  //to remove comp warning: not used
  //nch=nch;
  //to remove comp warning: not used
  //nrh=nrh;
  free((FREE_ARG) (m[nrl]+ncl-NR_END));
  free((FREE_ARG) (m+nrl-NR_END));
}

void free_fmmatrix(frame_mask **m, int32_t nrl, int32_t nrh, int32_t ncl, int32_t nch)
/* free an int matrix allocated by imatrix() */
{
  //to remove comp warning: not used
  //nch=nch;
  //to remove comp warning: not used
  //nrh=nrh;
  free((FREE_ARG) (m[nrl]+ncl-NR_END));
  free((FREE_ARG) (m+nrl-NR_END));
}

void free_submatrix(float **b, int32_t nrl, int32_t nrh, int32_t ncl, int32_t nch)
/* free a submatrix allocated by submatrix() */
{
  //to remove comp warning: not used
  //nch=nch;
  //to remove comp warning: not used
  //nrh=nrh;
  //to remove comp warning: not used
  //ncl=ncl;

  free((FREE_ARG) (b+nrl-NR_END));
}

void free_convert_matrix(float **b, int32_t nrl, int32_t nrh, int32_t ncl, int32_t nch)
/* free a matrix allocated by convert_matrix() */
{
  //to remove comp warning: not used
  //nch=nch;
  //to remove comp warning: not used
  //nrh=nrh;
  //to remove comp warning: not used
  //ncl=ncl;
  free((FREE_ARG) (b+nrl-NR_END));
}

void free_f3tensor(float ***t, int32_t nrl, int32_t nrh, int32_t ncl, int32_t nch,
		   int32_t ndl, int32_t ndh)
/* free a float f3tensor allocated by f3tensor() */
{
  //to remove comp warning: not used
  //nrh=nrh;
  //to remove comp warning: not used
  //nch=nch;
  //to remove comp warning: not used
  //ndh=ndh;

  free((FREE_ARG) (t[nrl][ncl]+ndl-NR_END));
  free((FREE_ARG) (t[nrl]+ncl-NR_END));
  free((FREE_ARG) (t+nrl-NR_END));
}

void free_d3tensor(double ***t, int32_t nrl, int32_t nrh, int32_t ncl, int32_t nch,
		   int32_t ndl, int32_t ndh)
/* free a double 3tensor allocated by d3tensor() */
{
  //to remove comp warning: not used
  //nrh=nrh;
  //to remove comp warning: not used
  //nch=nch;
  //to remove comp warning: not used
  //ndh=ndh;

  free((FREE_ARG) (t[nrl][ncl]+ndl-NR_END));
  free((FREE_ARG) (t[nrl]+ncl-NR_END));
  free((FREE_ARG) (t+nrl-NR_END));
}

void free_fd3tensor(frame_data ***t, int32_t nrl, int32_t nrh, int32_t ncl, int32_t nch,
		    int32_t ndl, int32_t ndh)
/* free a frame_data f3tensor allocated by f3tensor() */
{
  //to remove comp warning: not used
  //nrh=nrh;
  //to remove comp warning: not used
  //nch=nch;
  //to remove comp warning: not used
  //ndh=ndh;
  free((FREE_ARG) (t[nrl][ncl]+ndl-NR_END));
  free((FREE_ARG) (t[nrl]+ncl-NR_END));
  free((FREE_ARG) (t+nrl-NR_END));
}

void free_fm3tensor(frame_mask ***t, int32_t nrl, int32_t nrh, int32_t ncl, int32_t nch,
		    int32_t ndl, int32_t ndh)
/* free a float f3tensor allocated by f3tensor() */
{
  //to remove comp warning: not used
  //nrh=nrh;
  //to remove comp warning: not used
  //nch=nch;
  //to remove comp warning: not used
  //ndh=ndh;
  free((FREE_ARG) (t[nrl][ncl]+ndl-NR_END));
  free((FREE_ARG) (t[nrl]+ncl-NR_END));
  free((FREE_ARG) (t+nrl-NR_END));
}

void free_ul3tensor(uint32_t ***t, int32_t nrl, int32_t nrh, int32_t ncl, int32_t nch,
		    int32_t ndl, int32_t ndh)
/* free a float f3tensor allocated by f3tensor() */
{
  //to remove comp warning: not used
  //nrh=nrh;
  //to remove comp warning: not used
  //nch=nch;
  //to remove comp warning: not used
  //ndh=ndh;

  free((FREE_ARG) (t[nrl][ncl]+ndl-NR_END));
  free((FREE_ARG) (t[nrl]+ncl-NR_END));
  free((FREE_ARG) (t+nrl-NR_END));
}

void free_l3tensor(int32_t ***t, int32_t nrl, int32_t nrh, int32_t ncl, int32_t nch,
		   int32_t ndl, int32_t ndh)
/* free a float f3tensor allocated by f3tensor() */
{
  //to remove comp warning: not used
  //nrh=nrh;
  //to remove comp warning: not used
  //nch=nch;
  //to remove comp warning: not used
  //ndh=ndh;
  free((FREE_ARG) (t[nrl][ncl]+ndl-NR_END));
  free((FREE_ARG) (t[nrl]+ncl-NR_END));
  free((FREE_ARG) (t+nrl-NR_END));
}

void free_l4tensor(int32_t ****t, int32_t nal, int32_t nah, int32_t nrl, int32_t nrh, 
		   int32_t ncl, int32_t nch, int32_t ndl, int32_t ndh)
/* free an integer l4tensor allocated by f3tensor() */
{
  //to remove comp warning: not used
  //nah=nah;
  //to remove comp warning: not used
  //nrh=nrh;
  //to remove comp warning: not used
  //nch=nch;
  //to remove comp warning: not used
  //ndh=ndh;

  free((FREE_ARG) (t[nal][nrl][ncl]+ndl-NR_END));
  free((FREE_ARG) (t[nal][nrl]+ncl-NR_END));
  free((FREE_ARG) (t[nal]+nrl-NR_END));
  free((FREE_ARG) (t+nal-NR_END));
}

void matrix_product(double **A, double **B, double **C, int ra, int ca, int cb)
{
  /* Put in C the matrix product of A and B (in this order please!) */ 

  int k,j,m;
 
  C=dmatrix(1,ra,1,cb);
  if (!C) 
    {
      SCTPUT("Error in matrix product");
    }
 
  for (j=1; j<=ra; j++)
    {
      for (k=1; k<=cb; k++)
	{
	  C[j][k]=0;
	}
    }
  
  for (j=1; j<=ra; j++)
    {
      for (k=1; k<=cb; k++)
	{
	  for (m=1; m<=ca; m++)
	    { 
	      C[j][k] += A[j][m]*B[m][k];
	    } 
	}
    } 
  return ;
}
void matrix_sum(double **A, double **B, int ra, int ca)
{
 
  /* Put in A the matrix sum of A and B */ 
  int k,j;
 
  for (j=1; j<=ra; j++)
    {
      for (k=1; k<=ca; k++)
	{
	  A[j][k] += B[j][k];
	}
    } 
  return ;
}



#else /* ANSI */
/* traditional - K&R */

#include <stdio.h>
#include <flames_uves.h>
#define NR_END 1
#define FREE_ARG char*

void nrerror(error_text)
     char error_text[];
/* Numerical Recipes standard error handler */
{
  /*
    ---------- Let's comment out the non-MIDAS compliant items----------
 
    fprintf(stderr,"Numerical Recipes run-time error...\n");
    fprintf(stderr,"%s\n",error_text);
    fprintf(stderr,"...now exiting to system...\n");
  */    
  void exit();
  char output[70];
 
  SCTPUT("Numerical Recipes run-time error...\n"); 
  sprintf(output, "%s\n", error_text);
  SCTPUT(output); 
  SCTPUT("...now exiting to system...\n"); 
  SCSEPI();
  return flames_midas_fail();
}

float *vector(nl,nh)
     int32_t nh,nl;
     /* allocate a float vector with subscript range v[nl..nh] */
{
  float *v;

  v=(float *) calloc((unsigned int) (nh-nl+1+NR_END), sizeof(float));
  if (!v) nrerror("allocation failure in vector()");
  return v-nl+NR_END;
}

int *ivector(nl,nh)
     int32_t nh,nl;
     /* allocate an int vector with subscript range v[nl..nh] */
{
  int *v;

  v=(int *) calloc((unsigned int) (nh-nl+1+NR_END), sizeof(int));
  if (!v) nrerror("allocation failure in ivector()");
  return v-nl+NR_END;
}

unsigned int *uivector(nl,nh)
     int32_t nh,nl;
     /* allocate an int vector with subscript range v[nl..nh] */
{
  unsigned int *v;

  v=(unsigned int *) calloc((unsigned int) (nh-nl+1+NR_END), 
			    sizeof(unsigned int));
  if (!v) {
	  nrerror("allocation failure in uivector()");
  }
  return v-nl+NR_END;
}

char *cvector(nl,nh)
     int32_t nh,nl;
     /* allocate a char vector with subscript range v[nl..nh] */
{
  char *v;

  v=(char *) calloc((unsigned int) (nh-nl+1+NR_END), sizeof(char));
  if (!v) {
	  nrerror("allocation failure in cvector()");
  }
  return v-nl+NR_END;
}

char *ucvector(nl,nh)
     int32_t nh,nl;
     /* allocate an unsigned char vector with subscript range v[nl..nh] */
{
  unsigned char *v;

  v=(unsigned char *) calloc((unsigned int) (nh-nl+1+NR_END), 
			     sizeof(unsigned char));
  if (!v) {
	  nrerror("allocation failure in ucvector()");
  }
  return v-nl+NR_END;
}

int32_t *lvector(nl,nh)
     int32_t nh,nl;
     /* allocate an uint32_t vector with subscript range v[nl..nh] */
{
  int32_t *v;

  v=(int32_t *) calloc((unsigned int) (nh-nl+1+NR_END), 
			sizeof(int32_t));
  if (!v) {
	  nrerror("allocation failure in lvector()");
  }
  return v-nl+NR_END;
}

uint32_t *ulvector(nl,nh)
     int32_t nh,nl;
     /* allocate an uint32_t vector with subscript range v[nl..nh] */
{
  uint32_t *v;

  v=(uint32_t*) calloc((unsigned int) (nh-nl+1+NR_END), 
				sizeof(uint32_t));
  if (!v) {
	  nrerror("allocation failure in ulvector()");
  }
  return v-nl+NR_END;
}

double *dvector(nl,nh)
     int32_t nh,nl;
     /* allocate a double vector with subscript range v[nl..nh] */
{
  double *v;

  v=(double *) calloc((unsigned int) (nh-nl+1+NR_END), sizeof(double));
  if (!v) {
	  nrerror("allocation failure in dvector()");
  }
  return v-nl+NR_END;
}

double *fdvector(nl,nh)
     int32_t nh,nl;
     /* allocate a frame_data vector with subscript range v[nl..nh] */
{
  frame_data *v;

  v=(frame_data *) calloc((unsigned int) (nh-nl+1+NR_END), 
			  sizeof(frame_data));
  if (!v) {
	  nrerror("allocation failure in dvector()");
  }
  return v-nl+NR_END;
}

double *fmvector(nl,nh)
     int32_t nh,nl;
     /* allocate a frame_mask vector with subscript range v[nl..nh] */
{
  frame_mask *v;

  v=(frame_mask *) calloc((unsigned int) (nh-nl+1+NR_END), 
			  sizeof(frame_mask));
  if (!v) {
	  nrerror("allocation failure in dvector()");
  }
  return v-nl+NR_END;
}

float **matrix(nrl,nrh,ncl,nch)
     int32_t nch,ncl,nrh,nrl;
     /* allocate a float matrix with subscript range m[nrl..nrh][ncl..nch] */
{
  int32_t i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
  float **m;

  /* allocate pointers to rows */
  m=(float **) calloc((unsigned int)(nrow+NR_END), sizeof(float*));
  if (!m) {
	  nrerror("allocation failure 1 in matrix()");
  }
  m += NR_END;
  m -= nrl;

  /* allocate rows and set pointers to them */
  m[nrl]=(float *) calloc((unsigned int)(nrow*ncol+NR_END), 
			  sizeof(float));
  if (!m[nrl]) {
	  nrerror("allocation failure 2 in matrix()");
  }
  m[nrl] += NR_END;
  m[nrl] -= ncl;

  for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol;

  /* return pointer to array of pointers to rows */
  return m;
}

char **cmatrix(nrl,nrh,ncl,nch)
     int32_t nch,ncl,nrh,nrl;
     /* allocate a float matrix with subscript range m[nrl..nrh][ncl..nch] */
{
  int32_t i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
  char **m;

  /* allocate pointers to rows */
  m=(char **) calloc((unsigned int)(nrow+NR_END), sizeof(char*));
  if (!m) {
	  nrerror("allocation failure 1 in cmatrix()");
  }
  m += NR_END;
  m -= nrl;

  /* allocate rows and set pointers to them */
  m[nrl]=(char *) calloc((unsigned int)(nrow*ncol+NR_END), 
			 sizeof(char));
  if (!m[nrl]) {
	  nrerror("allocation failure 2 in cmatrix()");
  }
  m[nrl] += NR_END;
  m[nrl] -= ncl;

  for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol;

  /* return pointer to array of pointers to rows */
  return m;
}

double **dmatrix(nrl,nrh,ncl,nch)
     int32_t nch,ncl,nrh,nrl;
     /* allocate a double matrix with subscript range m[nrl..nrh][ncl..nch] */
{
  int32_t i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
  double **m;

  /* allocate pointers to rows */
  m=(double **) calloc((unsigned int)(nrow+NR_END), sizeof(double*));
  if (!m) {
	  nrerror("allocation failure 1 in dmatrix()");
  }
  m += NR_END;
  m -= nrl;

  /* allocate rows and set pointers to them */
  m[nrl]=(double *) calloc((unsigned int)(nrow*ncol+NR_END), 
			   sizeof(double));
  if (!m[nrl]) nrerror("allocation failure 2 in dmatrix()");
  m[nrl] += NR_END;
  m[nrl] -= ncl;

  for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol;

  /* return pointer to array of pointers to rows */
  return m;
}

int **imatrix(nrl,nrh,ncl,nch)
     int32_t nch,ncl,nrh,nrl;
     /* allocate a int matrix with subscript range m[nrl..nrh][ncl..nch] */
{
  int32_t i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
  int **m;

  /* allocate pointers to rows */
  m=(int **) calloc((unsigned int)(nrow+NR_END), sizeof(int*));
  if (!m) {
	  nrerror("allocation failure 1 in imatrix()");
  }
  m += NR_END;
  m -= nrl;


  /* allocate rows and set pointers to them */
  m[nrl]=(int *) calloc((unsigned int)(nrow*ncol+NR_END), sizeof(int));
  if (!m[nrl]) nrerror("allocation failure 2 in imatrix()");
  m[nrl] += NR_END;
  m[nrl] -= ncl;

  for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol;

  /* return pointer to array of pointers to rows */
  return m;
}

uint32_t **ulmatrix(nrl,nrh,ncl,nch)
     int32_t nch,ncl,nrh,nrl;
     /* allocate a int matrix with subscript range m[nrl..nrh][ncl..nch] */
{
  int32_t i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
  uint32_t **m;

  /* allocate pointers to rows */
  m=(uint32_t **) calloc((unsigned int)(nrow+NR_END), 
				  sizeof(uint32_t*));
  if (!m) {
	  nrerror("allocation failure 1 in ulmatrix()");
  }
  m += NR_END;
  m -= nrl;


  /* allocate rows and set pointers to them */
  m[nrl]=(uint32_t *) calloc((unsigned int)(nrow*ncol+NR_END), 
				      sizeof(uint32_t));
  if (!m[nrl]) nrerror("allocation failure 2 in ulmatrix()");
  m[nrl] += NR_END;
  m[nrl] -= ncl;

  for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol;

  /* return pointer to array of pointers to rows */
  return m;
}

int32_t **lmatrix(nrl,nrh,ncl,nch)
     int32_t nch,ncl,nrh,nrl;
     /* allocate a int matrix with subscript range m[nrl..nrh][ncl..nch] */
{
  int32_t i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
  int32_t **m;

  /* allocate pointers to rows */
  m=(int32_t **) calloc((unsigned int)(nrow+NR_END), sizeof(int32_t*));
  if (!m) {
	  nrerror("allocation failure 1 in lmatrix()");
  }
  m += NR_END;
  m -= nrl;


  /* allocate rows and set pointers to them */
  m[nrl]=(int32_t *) calloc((unsigned int)(nrow*ncol+NR_END), 
			     sizeof(int32_t));
  if (!m[nrl]) nrerror("allocation failure 2 in lmatrix()");
  m[nrl] += NR_END;
  m[nrl] -= ncl;

  for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol;

  /* return pointer to array of pointers to rows */
  return m;
}

frame_data **fdmatrix(nrl,nrh,ncl,nch)
     int32_t nch,ncl,nrh,nrl;
     /* allocate a frame_data matrix with subscript range m[nrl..nrh][ncl..nch] */
{
  int32_t i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
  frame_data **m;

  /* allocate pointers to rows */
  m=(frame_data **) calloc((unsigned int)(nrow+NR_END), 
			   sizeof(frame_data*));
  if (!m) {
	  nrerror("allocation failure 1 in fdmatrix()");
  }
  m += NR_END;
  m -= nrl;


  /* allocate rows and set pointers to them */
  m[nrl]=(frame_data *) calloc((unsigned int)(nrow*ncol+NR_END), 
			       sizeof(frame_data));
  if (!m[nrl]) nrerror("allocation failure 2 in fdmatrix()");
  m[nrl] += NR_END;
  m[nrl] -= ncl;

  for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol;

  /* return pointer to array of pointers to rows */
  return m;
}

frame_mask **fmmatrix(nrl,nrh,ncl,nch)
     int32_t nch,ncl,nrh,nrl;
     /* allocate a frame_mask matrix with subscript range m[nrl..nrh][ncl..nch] */
{
  int32_t i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
  frame_mask **m;

  /* allocate pointers to rows */
  m=(frame_mask **) calloc((unsigned int)(nrow+NR_END), 
			   sizeof(frame_mask*));
  if (!m) {
	  nrerror("allocation failure 1 in fmmatrix()");
  }
  m += NR_END;
  m -= nrl;


  /* allocate rows and set pointers to them */
  m[nrl]=(frame_mask *) calloc((unsigned int)(nrow*ncol+NR_END), 
			       sizeof(frame_mask));
  if (!m[nrl]) nrerror("allocation failure 2 in fmmatrix()");
  m[nrl] += NR_END;
  m[nrl] -= ncl;

  for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol;

  /* return pointer to array of pointers to rows */
  return m;
}

float **submatrix(a,oldrl,oldrh,oldcl,oldch,newrl,newcl)
     float **a;
     int32_t newcl,newrl,oldch,oldcl,oldrh,oldrl;
     /* point a submatrix [newrl..][newcl..] to a[oldrl..oldrh][oldcl..oldch] */
{
  int32_t i,j,nrow=oldrh-oldrl+1,ncol=oldcl-newcl;
  float **m;

  /* allocate array of pointers to rows */
  m=(float **) calloc((unsigned int) (nrow+NR_END), sizeof(float*));
  if (!m) {
	  nrerror("allocation failure in submatrix()");
  }
  m += NR_END;
  m -= newrl;

  /* set pointers to rows */
  for(i=oldrl,j=newrl;i<=oldrh;i++,j++) m[j]=a[i]+ncol;

  /* return pointer to array of pointers to rows */
  return m;
}

float **convert_matrix(a,nrl,nrh,ncl,nch)
     float *a;
     int32_t nch,ncl,nrh,nrl;
     /* allocate a float matrix m[nrl..nrh][ncl..nch] that points to the matrix
	declared in the standard C manner as a[nrow][ncol], where nrow=nrh-nrl+1
	and ncol=nch-ncl+1. The routine should be called with the address
	&a[0][0] as the first argument. */
{
  int32_t i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1;
  float **m;

  /* allocate pointers to rows */
  m=(float **) calloc((unsigned int) (nrow+NR_END), sizeof(float*));
  if (!m)    {
	  nrerror("allocation failure in convert_matrix()");
  }
  m += NR_END;
  m -= nrl;

  /* set pointers to rows */
  m[nrl]=a-ncl;
  for(i=1,j=nrl+1;i<nrow;i++,j++) m[j]=m[j-1]+ncol;
  /* return pointer to array of pointers to rows */
  return m;
}

float ***f3tensor(nrl,nrh,ncl,nch,ndl,ndh)
     int32_t nch,ncl,ndh,ndl,nrh,nrl;
     /* allocate a float 3tensor with range t[nrl..nrh][ncl..nch][ndl..ndh] */
{
  int32_t i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1,ndep=ndh-ndl+1;
  float ***t;

  /* allocate pointers to pointers to rows */
  t=(float ***) calloc((unsigned int)(nrow+NR_END), sizeof(float**));
  if (!t) {
	  nrerror("allocation failure 1 in f3tensor()");
  }
  t += NR_END;
  t -= nrl;

  /* allocate pointers to rows and set pointers to them */
  t[nrl]=(float **) calloc((unsigned int)(nrow*ncol+NR_END), 
			   sizeof(float*));
  if (!t[nrl]) nrerror("allocation failure 2 in f3tensor()");
  t[nrl] += NR_END;
  t[nrl] -= ncl;

  /* allocate rows and set pointers to them */
  t[nrl][ncl]=(float *) calloc((unsigned int)(nrow*ncol*ndep+NR_END), 
			       sizeof(float));
  if (!t[nrl][ncl]) nrerror("allocation failure 3 in f3tensor()");
  t[nrl][ncl] += NR_END;
  t[nrl][ncl] -= ndl;

  for(j=ncl+1;j<=nch;j++) t[nrl][j]=t[nrl][j-1]+ndep;
  for(i=nrl+1;i<=nrh;i++) {
    t[i]=t[i-1]+ncol;
    t[i][ncl]=t[i-1][ncl]+ncol*ndep;
    for(j=ncl+1;j<=nch;j++) t[i][j]=t[i][j-1]+ndep;
  }

  /* return pointer to array of pointers to rows */
  return t;
}

frame_data ***fd3tensor(nrl,nrh,ncl,nch,ndl,ndh)
     int32_t nch,ncl,ndh,ndl,nrh,nrl;
     /* allocate a frame_data 3tensor with range t[nrl..nrh][ncl..nch][ndl..ndh] */
{
  int32_t i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1,ndep=ndh-ndl+1;
  frame_data ***t;

  /* allocate pointers to pointers to rows */
  t=(frame_data ***) calloc((unsigned int)(nrow+NR_END), 
			    sizeof(frame_data**));
  if (!t) {
	  nrerror("allocation failure 1 in fd3tensor()");
  }
  t += NR_END;
  t -= nrl;

  /* allocate pointers to rows and set pointers to them */
  t[nrl]=(frame_data **) calloc((unsigned int)(nrow*ncol+NR_END), 
				sizeof(frame_data*));
  if (!t[nrl]) nrerror("allocation failure 2 in fd3tensor()");
  t[nrl] += NR_END;
  t[nrl] -= ncl;

  /* allocate rows and set pointers to them */
  t[nrl][ncl]=
    (frame_data *) calloc((unsigned int)(nrow*ncol*ndep+NR_END), 
			  sizeof(frame_data));
  if (!t[nrl][ncl]) nrerror("allocation failure 3 in fd3tensor()");
  t[nrl][ncl] += NR_END;
  t[nrl][ncl] -= ndl;

  for(j=ncl+1;j<=nch;j++) t[nrl][j]=t[nrl][j-1]+ndep;
  for(i=nrl+1;i<=nrh;i++) {
    t[i]=t[i-1]+ncol;
    t[i][ncl]=t[i-1][ncl]+ncol*ndep;
    for(j=ncl+1;j<=nch;j++) t[i][j]=t[i][j-1]+ndep;
  }

  /* return pointer to array of pointers to rows */
  return t;
}

double ***d3tensor(nrl,nrh,ncl,nch,ndl,ndh)
     int32_t nch,ncl,ndh,ndl,nrh,nrl;
     /* allocate a double 3tensor with range t[nrl..nrh][ncl..nch][ndl..ndh] */
{
  int32_t i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1,ndep=ndh-ndl+1;
  double ***t;

  /* allocate pointers to pointers to rows */
  t=(double ***) {
	  calloc((unsigned int)(nrow+NR_END), sizeof(double**));
  }
  if (!t) nrerror("allocation failure 1 in d3tensor()");
  t += NR_END;
  t -= nrl;

  /* allocate pointers to rows and set pointers to them */
  t[nrl]=(double **) calloc((unsigned int)(nrow*ncol+NR_END), 
			    sizeof(double*));
  if (!t[nrl]) nrerror("allocation failure 2 in d3tensor()");
  t[nrl] += NR_END;
  t[nrl] -= ncl;

  /* allocate rows and set pointers to them */
  t[nrl][ncl]=(double *) calloc((unsigned int)(nrow*ncol*ndep+NR_END), 
				sizeof(double));
  if (!t[nrl][ncl]) nrerror("allocation failure 3 in d3tensor()");
  t[nrl][ncl] += NR_END;
  t[nrl][ncl] -= ndl;

  for(j=ncl+1;j<=nch;j++) t[nrl][j]=t[nrl][j-1]+ndep;
  for(i=nrl+1;i<=nrh;i++) {
    t[i]=t[i-1]+ncol;
    t[i][ncl]=t[i-1][ncl]+ncol*ndep;
    for(j=ncl+1;j<=nch;j++) t[i][j]=t[i][j-1]+ndep;
  }

  /* return pointer to array of pointers to rows */
  return t;
}

frame_data ***fd3tensor(nrl,nrh,ncl,nch,ndl,ndh)
     int32_t nch,ncl,ndh,ndl,nrh,nrl;
     /* allocate a frame_data 3tensor with range t[nrl..nrh][ncl..nch][ndl..ndh] */
{
  int32_t i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1,ndep=ndh-ndl+1;
  frame_data ***t;

  /* allocate pointers to pointers to rows */
  t=(frame_data ***) calloc((unsigned int)(nrow+NR_END), 
			    sizeof(frame_data**));
  if (!t) {
	  nrerror("allocation failure 1 in f3tensor()");
  }
  t += NR_END;
  t -= nrl;

  /* allocate pointers to rows and set pointers to them */
  t[nrl]=(frame_data **) calloc((unsigned int)(nrow*ncol+NR_END), 
				sizeof(frame_data*));
  if (!t[nrl]) nrerror("allocation failure 2 in f3tensor()");
  t[nrl] += NR_END;
  t[nrl] -= ncl;

  /* allocate rows and set pointers to them */
  t[nrl][ncl]=
    (frame_data *) calloc((unsigned int)(nrow*ncol*ndep+NR_END), 
			  sizeof(frame_data));
  if (!t[nrl][ncl]) nrerror("allocation failure 3 in f3tensor()");
  t[nrl][ncl] += NR_END;
  t[nrl][ncl] -= ndl;

  for(j=ncl+1;j<=nch;j++) t[nrl][j]=t[nrl][j-1]+ndep;
  for(i=nrl+1;i<=nrh;i++) {
    t[i]=t[i-1]+ncol;
    t[i][ncl]=t[i-1][ncl]+ncol*ndep;
    for(j=ncl+1;j<=nch;j++) t[i][j]=t[i][j-1]+ndep;
  }

  /* return pointer to array of pointers to rows */
  return t;
}

frame_mask ***fm3tensor(nrl,nrh,ncl,nch,ndl,ndh)
     int32_t nch,ncl,ndh,ndl,nrh,nrl;
     /* allocate a frame_mask 3tensor with range t[nrl..nrh][ncl..nch][ndl..ndh] */
{
  int32_t i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1,ndep=ndh-ndl+1;
  frame_mask ***t;

  /* allocate pointers to pointers to rows */
  t=(frame_mask ***) calloc((unsigned int)(nrow+NR_END), 
			    sizeof(frame_mask**));
  if (!t) {
	  nrerror("allocation failure 1 in f3tensor()");
  }
  t += NR_END;
  t -= nrl;

  /* allocate pointers to rows and set pointers to them */
  t[nrl]=(frame_mask **) calloc((unsigned int)(nrow*ncol+NR_END), 
				sizeof(frame_mask*));
  if (!t[nrl]) nrerror("allocation failure 2 in f3tensor()");
  t[nrl] += NR_END;
  t[nrl] -= ncl;

  /* allocate rows and set pointers to them */
  t[nrl][ncl]=
    (frame_mask *) calloc((unsigned int)(nrow*ncol*ndep+NR_END), 
			  sizeof(frame_mask));
  if (!t[nrl][ncl]) nrerror("allocation failure 3 in f3tensor()");
  t[nrl][ncl] += NR_END;
  t[nrl][ncl] -= ndl;

  for(j=ncl+1;j<=nch;j++) t[nrl][j]=t[nrl][j-1]+ndep;
  for(i=nrl+1;i<=nrh;i++) {
    t[i]=t[i-1]+ncol;
    t[i][ncl]=t[i-1][ncl]+ncol*ndep;
    for(j=ncl+1;j<=nch;j++) t[i][j]=t[i][j-1]+ndep;
  }

  /* return pointer to array of pointers to rows */
  return t;
}

uint32_t ***ul3tensor(nrl,nrh,ncl,nch,ndl,ndh)
     int32_t nch,ncl,ndh,ndl,nrh,nrl;
     /* allocate a frame_mask 3tensor with range t[nrl..nrh][ncl..nch][ndl..ndh] */
{
  int32_t i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1,ndep=ndh-ndl+1;
  uint32_t ***t;

  /* allocate pointers to pointers to rows */
  t=(uint32_t ***) calloc((unsigned int)(nrow+NR_END), 
				   sizeof(uint32_t**));
  if (!t) {
	  nrerror("allocation failure 1 in f3tensor()");
  }
  t += NR_END;
  t -= nrl;

  /* allocate pointers to rows and set pointers to them */
  t[nrl]=(uint32_t **) calloc((unsigned int)(nrow*ncol+NR_END), 
				       sizeof(uint32_t*));
  if (!t[nrl]) nrerror("allocation failure 2 in f3tensor()");
  t[nrl] += NR_END;
  t[nrl] -= ncl;

  /* allocate rows and set pointers to them */
  t[nrl][ncl]=
    (uint32_t *) calloc((unsigned int)(nrow*ncol*ndep+NR_END), 
				 sizeof(uint32_t));
  if (!t[nrl][ncl]) nrerror("allocation failure 3 in f3tensor()");
  t[nrl][ncl] += NR_END;
  t[nrl][ncl] -= ndl;

  for(j=ncl+1;j<=nch;j++) t[nrl][j]=t[nrl][j-1]+ndep;
  for(i=nrl+1;i<=nrh;i++) {
    t[i]=t[i-1]+ncol;
    t[i][ncl]=t[i-1][ncl]+ncol*ndep;
    for(j=ncl+1;j<=nch;j++) t[i][j]=t[i][j-1]+ndep;
  }

  /* return pointer to array of pointers to rows */
  return t;
}

int32_t ***l3tensor(nrl,nrh,ncl,nch,ndl,ndh)
     int32_t nch,ncl,ndh,ndl,nrh,nrl;
     /* allocate a int32_t 3tensor with range t[nrl..nrh][ncl..nch][ndl..ndh] */
{
  int32_t i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1,ndep=ndh-ndl+1;
  int32_t ***t;

  /* allocate pointers to pointers to rows */
  t=(int32_t ***) calloc((unsigned int)(nrow+NR_END), 
			  sizeof(int32_t**));
  if (!t) {
	  nrerror("allocation failure 1 in f3tensor()");
  }
  t += NR_END;
  t -= nrl;

  /* allocate pointers to rows and set pointers to them */
  t[nrl]=(int32_t **) calloc((unsigned int)(nrow*ncol+NR_END), 
			      sizeof(int32_t*));
  if (!t[nrl]) nrerror("allocation failure 2 in f3tensor()");
  t[nrl] += NR_END;
  t[nrl] -= ncl;

  /* allocate rows and set pointers to them */
  t[nrl][ncl]=(int32_t *) calloc((unsigned int)(nrow*ncol*ndep+NR_END), 
				  sizeof(int32_t));
  if (!t[nrl][ncl]) nrerror("allocation failure 3 in f3tensor()");
  t[nrl][ncl] += NR_END;
  t[nrl][ncl] -= ndl;

  for(j=ncl+1;j<=nch;j++) t[nrl][j]=t[nrl][j-1]+ndep;
  for(i=nrl+1;i<=nrh;i++) {
    t[i]=t[i-1]+ncol;
    t[i][ncl]=t[i-1][ncl]+ncol*ndep;
    for(j=ncl+1;j<=nch;j++) t[i][j]=t[i][j-1]+ndep;
  }

  /* return pointer to array of pointers to rows */
  return t;
}

int32_t ***l4tensor(nal,nah,nrl,nrh,ncl,nch,ndl,ndh)
     int32_t nch,ncl,ndh,ndl,nrh,nrl,nah,nal;
     /* allocate a int32_t 4tensor with range 
	t[nal..nah][nrl..nrh][ncl..nch][ndl..ndh] */
{
  int32_t i,j,k,na=nah-nal+1,nrow=nrh-nrl+1,ncol=nch-ncl+1,ndep=ndh-ndl+1;
  int32_t ****t;

  /* allocate pointers to pointers to rows */
  t=(int32_t ****) calloc((unsigned int)(na+NR_END), 
			   sizeof(int32_t***));
  if (!t) {
	  nrerror("allocation failure 1 in l4tensor()");
  }
  t += NR_END;
  t -= nal;

  /* allocate pointers to pointers to rows and set pointers to them */
  t[nal]=(int32_t ***) calloc((unsigned int)(na*nrow+NR_END), 
			       sizeof(int32_t**));
  if (!t[nrl]) nrerror("allocation failure 2 in l4tensor()");
  t[nal] += NR_END;
  t[nal] -= nrl;

  /* allocate pointers to rows and set pointers to them */
  t[nal][nrl]=(int32_t **) calloc((unsigned int)(na*nrow*ncol+NR_END), 
				   sizeof(int32_t*));
  if (!t[nal][nrl]) nrerror("allocation failure 3 in l4tensor()");
  t[nal][nrl] += NR_END;
  t[nal][nrl] -= ncl;

  /* allocate rows and set pointers to them */
  t[nal][nrl][ncl]=
    (int32_t *) calloc((unsigned int)(na*nrow*ncol*ndep+NR_END), 
			sizeof(int32_t));
  if (!t[nal][nrl][ncl]) nrerror("allocation failure 4 in l4tensor()");
  t[nal][nrl][ncl] += NR_END;
  t[nal][nrl][ncl] -= ndl;

  for(k=ncl+1;k<=nch;k++) t[nal][nrl][k]=t[nal][nrl][k-1]+ndep;
  for(j=nrl+1;j<=nrh;j++) {
    t[nal][j] = t[nal][j-1]+ncol;
    t[nal][j][ncl] = t[nal][j-1][ncl]+ncol*ndep;
    for(k=ncl+1;k<=nch;k++) t[nal][j][k]=t[nal][j][k-1]+ndep;
  }
  for(i=nal+1;i<=nah;i++) {
    t[i]=t[i-1]+nrow;
    t[i][nrl] = t[i-1][nrl]+nrow*ncol;
    t[i][nrl][ncl] = t[i-1][nrl][ncl]+nrow*ncol*ndep;
    for(k=ncl+1;k<=nch;k++) t[i][nrl][k]=t[i][nrl][k-1]+ndep;
    for(j=nrl+1;j<=nrh;j++) {
      t[i][j] = t[i][j-1]+ncol;
      t[i][j][ncl] = t[i][j-1][ncl]+ncol*ndep;
      for(k=ncl+1;k<=nch;k++) t[i][j][k]=t[i][j][k-1]+ndep;
    }
  }

  /* return pointer to array of pointers to rows */
  return t;
}

void free_vector(v,nl,nh)
     float *v;
     int32_t nh,nl;
     /* free a float vector allocated with vector() */
{
  free((FREE_ARG) (v+nl-NR_END));
}

void free_ivector(v,nl,nh)
     int *v;
     int32_t nh,nl;
     /* free an int vector allocated with ivector() */
{
  free((FREE_ARG) (v+nl-NR_END));
}

void free_uivector(v,nl,nh)
     unsigned int *v;
     int32_t nh,nl;
     /* free an int vector allocated with uivector() */
{
  free((FREE_ARG) (v+nl-NR_END));
}

void free_cvector(v,nl,nh)
     int32_t nh,nl;
     char *v;
     /* free a char vector allocated with cvector() */
{
  free((FREE_ARG) (v+nl-NR_END));
}

void free_ucvector(v,nl,nh)
     int32_t nh,nl;
     unsigned char *v;
     /* free a char vector allocated with ucvector() */
{
  free((FREE_ARG) (v+nl-NR_END));
}

void free_lvector(v,nl,nh)
     int32_t nh,nl;
     int32_t *v;
     /* free an uint32_t vector allocated with lvector() */
{
  free((FREE_ARG) (v+nl-NR_END));
}

void free_ulvector(v,nl,nh)
     int32_t nh,nl;
     uint32_t *v;
     /* free an uint32_t vector allocated with ulvector() */
{
  free((FREE_ARG) (v+nl-NR_END));
}

void free_dvector(v,nl,nh)
     double *v;
     int32_t nh,nl;
     /* free a double vector allocated with dvector() */
{
  free((FREE_ARG) (v+nl-NR_END));
}

void free_fdvector(v,nl,nh)
     frame_data *v;
     int32_t nh,nl;
     /* free a frame_data vector allocated with dvector() */
{
  free((FREE_ARG) (v+nl-NR_END));
}

void free_fmvector(v,nl,nh)
     frame_mask *v;
     int32_t nh,nl;
     /* free a double vector allocated with dvector() */
{
  free((FREE_ARG) (v+nl-NR_END));
}

void free_matrix(m,nrl,nrh,ncl,nch)
     float **m;
     int32_t nch,ncl,nrh,nrl;
     /* free a float matrix allocated by matrix() */
{
  free((FREE_ARG) (m[nrl]+ncl-NR_END));
  free((FREE_ARG) (m+nrl-NR_END));
}

void free_cmatrix(m,nrl,nrh,ncl,nch)
     char **m;
     int32_t nch,ncl,nrh,nrl;
     /* free a char matrix allocated by cmatrix() */
{
  free((FREE_ARG) (m[nrl]+ncl-NR_END));
  free((FREE_ARG) (m+nrl-NR_END));
}

void free_dmatrix(m,nrl,nrh,ncl,nch)
     double **m;
     int32_t nch,ncl,nrh,nrl;
     /* free a double matrix allocated by dmatrix() */
{
  free((FREE_ARG) (m[nrl]+ncl-NR_END));
  free((FREE_ARG) (m+nrl-NR_END));
}

void free_ulmatrix(m,nrl,nrh,ncl,nch)
     uint32_t **m;
     int32_t nch,ncl,nrh,nrl;
     /* free an int matrix allocated by imatrix() */
{
  free((FREE_ARG) (m[nrl]+ncl-NR_END));
  free((FREE_ARG) (m+nrl-NR_END));
}

void free_lmatrix(m,nrl,nrh,ncl,nch)
     int32_t **m;
     int32_t nch,ncl,nrh,nrl;
     /* free an int matrix allocated by imatrix() */
{
  free((FREE_ARG) (m[nrl]+ncl-NR_END));
  free((FREE_ARG) (m+nrl-NR_END));
}

void free_imatrix(m,nrl,nrh,ncl,nch)
     int **m;
     int32_t nch,ncl,nrh,nrl;
     /* free an int matrix allocated by imatrix() */
{
  free((FREE_ARG) (m[nrl]+ncl-NR_END));
  free((FREE_ARG) (m+nrl-NR_END));
}

void free_fdmatrix(m,nrl,nrh,ncl,nch)
     frame_data **m;
     int32_t nch,ncl,nrh,nrl;
     /* free a frame_data matrix allocated by imatrix() */
{
  free((FREE_ARG) (m[nrl]+ncl-NR_END));
  free((FREE_ARG) (m+nrl-NR_END));
}

void free_fmmatrix(m,nrl,nrh,ncl,nch)
     frame_mask **m;
     int32_t nch,ncl,nrh,nrl;
     /* free a frame_mask matrix allocated by imatrix() */
{
  free((FREE_ARG) (m[nrl]+ncl-NR_END));
  free((FREE_ARG) (m+nrl-NR_END));
}

void free_submatrix(b,nrl,nrh,ncl,nch)
     float **b;
     int32_t nch,ncl,nrh,nrl;
     /* free a submatrix allocated by submatrix() */
{
  free((FREE_ARG) (b+nrl-NR_END));
}

void free_convert_matrix(b,nrl,nrh,ncl,nch)
     float **b;
     int32_t nch,ncl,nrh,nrl;
     /* free a matrix allocated by convert_matrix() */
{
  free((FREE_ARG) (b+nrl-NR_END));
}

void free_f3tensor(t,nrl,nrh,ncl,nch,ndl,ndh)
     float ***t;
     int32_t nch,ncl,ndh,ndl,nrh,nrl;
     /* free a float f3tensor allocated by f3tensor() */
{
  free((FREE_ARG) (t[nrl][ncl]+ndl-NR_END));
  free((FREE_ARG) (t[nrl]+ncl-NR_END));
  free((FREE_ARG) (t+nrl-NR_END));
}

void free_d3tensor(t,nrl,nrh,ncl,nch,ndl,ndh)
     double ***t;
     int32_t nch,ncl,ndh,ndl,nrh,nrl;
     /* free a double 3tensor allocated by d3tensor() */
{
  free((FREE_ARG) (t[nrl][ncl]+ndl-NR_END));
  free((FREE_ARG) (t[nrl]+ncl-NR_END));
  free((FREE_ARG) (t+nrl-NR_END));
}

void free_fd3tensor(t,nrl,nrh,ncl,nch,ndl,ndh)
     frame_data ***t;
     int32_t nch,ncl,ndh,ndl,nrh,nrl;
     /* free a frame_data f3tensor allocated by f3tensor() */
{
  free((FREE_ARG) (t[nrl][ncl]+ndl-NR_END));
  free((FREE_ARG) (t[nrl]+ncl-NR_END));
  free((FREE_ARG) (t+nrl-NR_END));
}

void free_fm3tensor(t,nrl,nrh,ncl,nch,ndl,ndh)
     frame_mask ***t;
     int32_t nch,ncl,ndh,ndl,nrh,nrl;
     /* free a float f3tensor allocated by f3tensor() */
{
  free((FREE_ARG) (t[nrl][ncl]+ndl-NR_END));
  free((FREE_ARG) (t[nrl]+ncl-NR_END));
  free((FREE_ARG) (t+nrl-NR_END));
}

void free_ul3tensor(t,nrl,nrh,ncl,nch,ndl,ndh)
     uint32_t ***t;
     int32_t nch,ncl,ndh,ndl,nrh,nrl;
     /* free a float f3tensor allocated by f3tensor() */
{
  free((FREE_ARG) (t[nrl][ncl]+ndl-NR_END));
  free((FREE_ARG) (t[nrl]+ncl-NR_END));
  free((FREE_ARG) (t+nrl-NR_END));
}

void free_l3tensor(t,nrl,nrh,ncl,nch,ndl,ndh)
     int32_t ***t;
     int32_t nch,ncl,ndh,ndl,nrh,nrl;
     /* free a float f3tensor allocated by f3tensor() */
{
  free((FREE_ARG) (t[nrl][ncl]+ndl-NR_END));
  free((FREE_ARG) (t[nrl]+ncl-NR_END));
  free((FREE_ARG) (t+nrl-NR_END));
}

void free_l4tensor(t,nal,nah,nrl,nrh,ncl,nch,ndl,ndh)
     int32_t ***t;
     int32_t nch,ncl,ndh,ndl,nrh,nrl,nah,nal;
     /* free a int32_t l4tensor allocated by l4tensor() */
{
  free((FREE_ARG) (t[nal][nrl][ncl]+ndl-NR_END));
  free((FREE_ARG) (t[nal][nrl]+ncl-NR_END));
  free((FREE_ARG) (t[nal]+nrl-NR_END));
  free((FREE_ARG) (t+nal-NR_END));
}


void 
matrix_product(double** A, double** B, double** C, int ra, int ca, int cb)
{
 
  int k=0,j=0,m=0;

  if (C==0)
    {
      C=dmatrix(1,ra,1,cb);
    }  

  for (j=1; j<=ra; j++)
    {
      for (k=1; k<=cb; k++)
	{
	  C[j][k]=0;
	}
    }
  
  for (j=1; j<=ra; j++)
    {
      for (k=1; k<=cb; k++)
	{
	  for (m=1; m<=ca; m++)
	    { 
	      C[j][k] += A[j][m]*B[m][k];
	    } 
	}
    } 
  return ;
}

void 
matrix_sum(double** A, double** B, int ra, int ca)
{
 
  int k=0,j=0;
 
  for (j=1; j<=ra; j++)
    {
      for (k=1; k<=ca; k++)
	{
	  A[j][k] += B[j][k];
	}
    } 
  return ;
}


#endif /* ANSI */
