/* @(#)ast_bprec.c	19.1 (ES0-DMD) 02/25/03 13:53:52 */
/*===========================================================================
  Copyright (C) 1995 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
===========================================================================*/

/*+++++++++++++++       
.TYPE           Module
.IDENTIFICATION bprec.c
.VERSION 1.0	02-Mar-1987: Creation .
.VERSION 1.1	26-Oct-1988: Cosmetic modifications
.Language       C
.AUTHOR         Francois Ochsenbein [ESO-IPG]  
.KEYWORDS       Precession of Coordinates in B system.

.ENVIRONMENT	Any

.COMMENTS
This module uses the old (Newcomb) precession constants,
and assumes the FK4 system.
Dates must be expressed in {\em Besselian Years}.

\begin{TeX}

The precession may be applied on unit vectors (mnemonic {\tt u}), or
on equatorial coordinates (mnemonic {\tt q}). 

-----------------------------------------------------------------------*/

#include <trigo.h>
#include <ok.h>

#define DEBUG		0	/* Debugging option	*/

#define ze	Euler_angles[0]
#define theta	Euler_angles[1]
#define zeta	Euler_angles[2]

/*============================================================================*/
int preb_R (R, eq0, eq1)   
/*+++
.PURPOSE  Compute the precession matrix, using the old IAU constants.
	Newcomb). The resulting matrix is such that
\begin{TeX}
\quad $\vec{u}(t_1) = R \cdot \vec{u}(t_0)$ \quad (old to new frame).
\end{TeX}
.RETURNS OK
---*/
	double R[3][3];  /* OUT: rotation matrix */
	double eq0; 	/* IN: Initial equinox ( in Besselian Years)	*/
	double eq1; 	/* IN: Final equinox (in Besselian Years)	*/
{
 	double t0, dt;
	double Euler_angles[3];


  t0 = (eq0 - 1900.e0)/1000.e0;	/* Origin is tropical year 1900	*/
  dt = (eq1 - eq0)/1000.e0;

  zeta = dt*(23042.53e0+ t0*(139.73e0+0.06e0*t0) + 
	dt*(30.23e0+18.e0*dt-0.27e0*t0) ) /3600.e0;
  ze = zeta + dt*dt*(79.27e0+0.66e0*t0+0.32e0*dt)/3600.e0;
  theta = dt* (20046.85e0 - t0*(85.33e0+0.37*t0) - 
	dt*(42.67e0+0.37e0*t0+41.8e0*dt) )/3600.e0;
	
  return(tr_Euler(Euler_angles, R));

}

/*============================================================================*/
int preb_q (q0, q1, eq0, eq1)  
/*+++
.PURPOSE Performs a complete precession between 2 equinoxes,
	with the old (Newcomb) constants.
.METHOD  Compute the precession rotation matrix if necessary,
	then apply the rotation.
.RETURNS OK
---*/
	double q0[2];	/* IN: ra+dec at equinox eq0 in degrees */
	double q1[2]; 	/* OUT: precessed to equinox eq1	*/
	double eq0;	/* IN: Initial equinox	(Besselian Years)	*/
	double eq1;	/* IN: Final equinox (Besselian Years)		*/
{ 
	double us[3];
	
  if (eq0 == eq1)	/* No precession at all, same equinox!!!	*/
  {	q1[0] = q0[0];
	q1[1] = q0[1];
	return(OK);
  }

  tr_ou(q0, us);		/* Convert to unit vector...	*/

  preb_u(us, us, eq0, eq1);	/* precess on unit vectors...	*/
  
  return (tr_uo ( us, q1));	/* And finally -> coordinates	*/
}

/*============================================================================*/
int preb_u (u0, u1, eq0, eq1)  
/*+++
.PURPOSE Performs a complete precession between 2 equinoxes,
	with the old (Newcomb) constants.
.METHOD  Compute the precession rotation matrix if necessary,
	then apply the rotation.
.RETURNS OK
---*/
	double u0[3];	/* IN: Unit vector at equinox eq0 */
	double u1[3]; 	/* OUT: precessed to equinox eq1	*/
	double eq0;	/* IN: Initial equinox	(Besselian Years)	*/
	double eq1;	/* IN: Final equinox (Besselian Years)		*/
{ 
	static double _eq0 = 1900.e0;
	static double _eq1 = 1900.e0;
	static double _r[3][3]  = { 	{1.e0, 0.e0, 0.e0},
				{0.e0, 1.e0, 0.e0},
				{0.e0, 0.e0, 1.e0}};

  if (eq0 == eq1)	/* No precession at all, same equinox!!!	*/
  {	u1[0] = u0[0];
	u1[1] = u0[1];
	u1[2] = u0[2];
	return(OK);
  }

  if ( (_eq0 != eq0) || (_eq1 != eq1) )	/* Compute precession matrix	*/
  	_eq0 = eq0, _eq1 = eq1, preb_R(_r, eq0, eq1);

  return (tr_uu ( u0, u1, _r));	/* And finally rotate...	*/
}

