/*
 * This file is part of the ESO SINFONI Pipeline
 * Copyright (C) 2004,2005 European Southern Observatory
 *
 * 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, 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA
 */
/*----------------------------------------------------------------------------
   
   File name     :    sinfo_matrix.h
   Author         :    Nicolas Devillard
   Created on    :    1994
   Description    :    basic 2d sinfo_eclipse_matrix handling routines

 ---------------------------------------------------------------------------*/
/*
 $Id: sinfo_matrix.h,v 1.3 2007-06-06 07:10:45 amodigli Exp $
 $Author: amodigli $
 $Date: 2007-06-06 07:10:45 $
 $Revision: 1.3 $
 */

#ifndef SINFO_MATRIX_H
#define SINFO_MATRIX_H


/*---------------------------------------------------------------------------
                                   Includes
 ---------------------------------------------------------------------------*/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "sinfo_msg.h"
#include <cpl.h>

/*---------------------------------------------------------------------------
                                   Defines
 ---------------------------------------------------------------------------*/

#define _(b,i,j) (*((b)->m+(i)*(b)->nc+(j))) /* b(i,j)*/

#define mx_get(M,i,j)    ((M)->m[(i)+(j)*(M)->nc])
#define mx_set(M,i,j,v)    (mx_get(M,i,j)=v)


/*---------------------------------------------------------------------------
                                   New Types
 ---------------------------------------------------------------------------*/


typedef struct _MATRIX_ {
    double    *    m;
    int         nr;
    int         nc;
} sinfo_eclipse_matrix, *Matrix;



/*---------------------------------------------------------------------------
                          Function ANSI C prototypes
 ---------------------------------------------------------------------------*/

/**
  @name        sinfo_create_mx
  @memo        Allocates a new sinfo_eclipse_matrix.
  @param    nr    Number of rows.
  @param    nc    Number of columns.
  @return    Pointer to newly allocated sinfo_eclipse_matrix.
  @doc
 
  Allocates a new sinfo_eclipse_matrix.
 */

Matrix
sinfo_create_mx(int nr, int nc) ;

/**
  @name        sinfo_copy_mx
  @memo        Copy a sinfo_eclipse_matrix.
  @param    a    Matrix to copy.
  @return    Pointer to newly allocated sinfo_eclipse_matrix.
  @doc
 
  Copy a sinfo_eclipse_matrix.
 */

Matrix
sinfo_copy_mx(Matrix a) ;

/**
  @name        sinfo_close_mx
  @memo        Frees memory associated to a sinfo_eclipse_matrix.
  @param    a    Matrix to free.
  @return    void
  @doc
 
  Free a sinfo_eclipse_matrix.
 */

void
sinfo_close_mx(Matrix a) ;


/**
  @name        sinfo_mul_mx
  @memo        Multiplies 2 matrices.
  @param    a    Matrix on the left side of the multiplication.
  @param    b    Matrix on the right side of the multiplication.
  @return    Matrix a*b.
  @doc
 
  Multiply matrices.
 */

Matrix
sinfo_mul_mx(Matrix a, Matrix b) ;

/**
  @name        sinfo_invert_mx
  @memo        Inverts a sinfo_eclipse_matrix.
  @param    aa    (Square) sinfo_eclipse_matrix to sinfo_invert
  @return    Newly allocated sinfo_eclipse_matrix.
  @doc

  The sinfo_eclipse_matrix inversion procedure is hardcoded for 
  optimized speed in
  the case of 1x1, 2x2 and 3x3 matrices. This function is not suitable
  for large matrices.
 */

Matrix
sinfo_invert_mx(Matrix aa) ;


/**
  @name        sinfo_transp_mx
  @memo        Transposes a sinfo_eclipse_matrix.
  @param    a    Matrix to transpose.
  @return    Newly allocated sinfo_eclipse_matrix.
  @doc
 
  Transpose a sinfo_eclipse_matrix.
 */

Matrix
sinfo_transp_mx(Matrix a) ;

/**
  @name        sinfo_least_sq_mx
  @memo        Compute the solution of an equation using a pseudo-inverse.
  @param    A    Matrix.
  @param    B    Matrix.
  @return    Pointer to newly allocated sinfo_eclipse_matrix.
  @doc

  The equation is XA=B.

  The pseudo-inverse solution to this equation is defined as:
  \begin{verbatim}
  P = B.tA.inv(A.tA)
  \end{verbatim}

  P is solving the equation using a least-squares criterion.
  Demonstration left to the reader.
 */

Matrix sinfo_least_sq_mx(
    Matrix  A,
    Matrix  B
) ;


/**
  @name        sinfo_print_mx
  @memo        Prints out a sinfo_eclipse_matrix on stdout.
  @param    M        Matrix to print out
  @param    name    Name of the sinfo_eclipse_matrix to print out.
  @return    void
  @doc

  The sinfo_eclipse_matrix name is printed out, then all values row by row.
  Used for debugging purposes mostly.
 */

void sinfo_print_mx(
    Matrix  M,
    const char *  name
) ;


#endif
