/*Translated by FOR_C, v3.4.2 (-), on 07/09/115 at 08:31:45 */
/*FOR_C Options SET: ftn=u io=c no=p op=aimnv s=dbov str=l x=f - prototypes */
#include <math.h>
#include "fcrt.h"
#include "scov2.h"
#include <stdlib.h>
		/* PARAMETER translations */
#define	ONE	1.0e0
#define	ZERO	0.0e0
		/* end of PARAMETER translations */
 
void /*FUNCTION*/ scov2(
float *a,
long mdim,
long n,
long ip[],
float var,
long *ierr)
{
#define A(I_,J_)	(*(a+(I_)*(mdim)+(J_)))
	long int i, ip1, j, k, kp1;
	float tmp;
		/* OFFSET Vectors w/subscript range: 1 to dimension */
	long *const Ip = &ip[0] - 1;
		/* end of OFFSET VECTORS */
 
	/* Copyright (c) 1996 California Institute of Technology, Pasadena, CA.
	 * ALL RIGHTS RESERVED.
	 * Based on Government Sponsored Research NAS7-03001.
	 *>> 2001-02-13 SCOV2  Krogh   Fixed a comment.
	 *>> 1996-03-30 SCOV2  Krogh   Added external statement.
	 *>> 1994-11-11 SCOV2  Krogh   Declared all vars.
	 *>> 1994-10-20 SCOV2  Krogh  Changes to use M77CON
	 *>> 1989-10-20 SCOV2  CLL
	 *>> 1987-11-24 SCOV2  Lawson  Initial code.
	 *--S replaces "?": ?COV2, ?DOT, ?SWAP
	 *     Computes upper triangle of covariance matrix,
	 *     beginning with the triangular matrix, and permutation record, and
	 *     data error variance computed by _HFTI.
	 *     Thus, given a matrix, A, represented by the upper triangular
	 *     matrix in A(), and the permutation record in IP(), and the data
	 *     error variance, VAR, we compute the upper triangle of the
	 *     symmetric matrix, C = VAR * ((A**t)*A)**(-1).
	 *     Adapted from PROG2 in L & H book.
	 *     ------------------------------------------------------------------
	 *     Subprograms referenced directly: SDOT, SSWAP, IERM1
	 *     Other subprograms needed: ERMSG, IERV1, ERFIN, AMACH
	 *     ------------------------------------------------------------------
	 *                 Subroutine Arguments
	 *
	 *     A(,) [inout] On entry, contains the upper triangular matrix, A,
	 *                  in standard, not packed, storage.  This matrix could
	 *                  have been produced by _HFTI.  On return, contains the
	 *                  upper triangle of the symmetric unscaled covariance
	 *                  matrix.  Elements below the diagonal in A(,) will
	 *                  not be referenced.
	 *     MDIM [in]    First dimension of A(,).  Require MDIM .ge. N.
	 *     N [in]       Order of the matrix in A(,)
	 *     IP() [in]    Permutation record produced by _HFTI.
	 *     VAR  [in]    Estimate of variance of data error.
	 *     IERR [out]   Set to 0 if ok.  Set to J > 0 if the (J,J) element
	 *                  of the given matrix is zero.  In this latter case
	 *                  the covariance matrix cannot be computed and the
	 *                  contents of A(,) on return will be meaningless.
	 *     ------------------------------------------------------------------
	 *          This code was originally developed by Charles L. Lawson and
	 *     Richard J. Hanson at Jet Propulsion Laboratory in 1973.  The
	 *     original code was described and listed in the book,
	 *
	 *                  Solving Least Squares Problems
	 *                  C. L. Lawson and R. J. Hanson
	 *                  Prentice-Hall, 1974
	 *
	 *     Feb, 1985, C. L. Lawson & S. Y. Chan, JPL.  Adapted code from the
	 *     Lawson & Hanson book to Fortran 77 for use in the JPL MATH77
	 *     library.
	 *     Prefixing subprogram names with S or D for s.p. or d.p. versions.
	 *     Using generic names for intrinsic functions.
	 *     Adding calls to BLAS and MATH77 error processing subrs in some
	 *     program units.
	 *     1989-10-20 CLL Moved integer declaration earlier to avoid warning
	 *     msg from Cray compiler.
	 *     ------------------------------------------------------------------ */
 
	/*     ------------------------------------------------------------------
	 *     Replace upper triangular matrix U by its inverse, Inv(U)
	 * */
	for (j = 1; j <= n; j++)
	{
		if (A(j - 1,j - 1) == ZERO)
		{
			ierm1( "SCOV2", 1, 0, "Jth diagonal elt is zero", "J",
			 j, '.' );
			*ierr = j;
			return;
		}
		A(j - 1,j - 1) = ONE/A(j - 1,j - 1);
	}
 
	for (i = 1; i <= (n - 1); i++)
	{
		for (j = i + 1; j <= n; j++)
		{
			A(j - 1,i - 1) = -A(j - 1,j - 1)*sdot( j - i, &A(i - 1,i - 1),
			 mdim, &A(j - 1,i - 1), 1 );
		}
	}
 
	/*     Replace Inv(U) by upper triangle of Inv(u) * Trans(Inv(U))
	 *     multiplied by VAR.
	 * */
	for (i = 1; i <= n; i++)
	{
		for (j = i; j <= n; j++)
		{
			A(j - 1,i - 1) = var*sdot( n - j + 1, &A(j - 1,i - 1),
			 mdim, &A(j - 1,j - 1), mdim );
		}
	}
	/*                                 Permute rows & columns */
	for (i = n - 1; i >= 1; i--)
	{
		if (Ip[i] != i)
		{
			k = Ip[i];
			tmp = A(i - 1,i - 1);
			A(i - 1,i - 1) = A(k - 1,k - 1);
			A(k - 1,k - 1) = tmp;
			if (i > 1)
			{
				sswap( i - 1, &A(i - 1,0), 1, &A(k - 1,0), 1 );
			}
			ip1 = i + 1;
			if (ip1 < k)
			{
				sswap( k - i - 1, &A(ip1 - 1,i - 1), mdim, &A(k - 1,ip1 - 1),
				 1 );
			}
			kp1 = k + 1;
			if (kp1 <= n)
			{
				sswap( n - k, &A(kp1 - 1,i - 1), mdim, &A(kp1 - 1,k - 1),
				 mdim );
			}
		}
	}
	*ierr = 0;
	return;
#undef	A
} /* end of function */