/* Search program to find dates of equinox or new moon.  */

#define STARTDATE  2439935.5
#define ENDDATE    2445000.5
/* Define one of these nonzero, the others zero.  */
#define NEWMOON 0
#define FULLMOON 1
#define EQUINOX 0

#include "kep.h"
/* Conversion factors between degrees and radians */
double DTR = 1.7453292519943295769e-2;
double RTD = 5.7295779513082320877e1;
double RTS = 2.0626480624709635516e5; /* arc seconds per radian */
double STR = 4.8481368110953599359e-6; /* radians per arc second */
double PI = 3.14159265358979323846;
double TPI = 6.28318530717958647693;

extern double PI;

/* Standard epochs.  Note Julian epochs (J) are measured in
 * years of 365.25 days.
 */
double J2000 = 2451545.0;	/* 2000 January 1.5 */
double B1950 = 2433282.423;	/* 1950 January 0.923 Besselian epoch */
double J1900 = 2415020.0;	/* 1900 January 0, 12h UT */

double sqrt(), asin(), log();

/* coordinates of object
 */
int objnum = 0;	/* I.D. number of object */

/* ecliptic polar coordinates:
 * longitude, latitude in radians
 * radius in au
 */
double FAR obpolar[3];

struct orbit objorb = {
"Object         ",
2446800.5,
0.0,
0.0,
102.884,
0.999999,
0.985611,
0.016713,
1.1791,
2446800.5,
-3.86,
0.0,
0, /* &ear404, */
0.0,
0.0,
0.0
};

double appobj[3];


/* coordinates of Earth
 */
/* Heliocentric rectangular equatorial position
 * of the earth at time TDT re equinox J2000
 */
double FAR rearth[3];
double vearth[3];

/* Corresponding polar coordinates of earth:
 * longitude and latitude in radians, radius in au
 */
double FAR eapolar[3];

extern struct plantbl ear404;
struct orbit earth = {
"Earth          ",
2446800.5,
0.0,
0.0,
102.884,
0.999999,
0.985611,
0.016713,
1.1791,
2446800.5,
-3.86,
0.0,
&ear404,
0.0,
0.0,
0.0
};

/* Julian date of ephemeris */
double JD;
double TDT;
double UT;

/* flag = 0 if TDT assumed = UT,
 *      = 1 if input time is TDT,
 *      = 2 if input time is UT.
 */
int jdflag = 0;

/* correction vector, saved for display  */
double dp[3];

/* display formats for printf() */
extern char *intfmt, *dblfmt;

/* display enable flag */
int prtflg = 0;

double dradt, ddecdt;
extern double FAR moonpol[];
extern double FAR moonpp[];

double zgetdate(), gethms();
double func(), search();
int apparent();

int main()
{
  double t, t0;

  kinit();
  objnum = 0;
  t0 = STARTDATE;
  while( t0 <= ENDDATE )
    {
      prtflg = 0;
#if EQUINOX
      t = search( t0, 0.0, 364.0 );
#endif
#if NEWMOON
      t = search( t0, PI, 27.0 );
#endif
#if FULLMOON
      t = search( t0, 0.0, 27.0 );
#endif
      TDT = t;
      printf("%.4f ", t);
      prtflg = 1;
      jtocal(t);
      t0 = t;
    }
exit(0);
}

/* Search for desired conjunction.
   Step forward DELTA days from date T.  Then begin searching
   for the date at which the desired function equals Y.  */
double search(t, y, delta)
double t, y, delta;
{
  double tl, tm, th, yl, ym, yh, e;

  tl = t;
  yl = func(t);
  th = tl + delta;
  yh = yl;
  /* Bracket the solution date.  */
  do
    {
      tl = th;
      yl = yh;
      th = th + 1.0;
      yh = func(th);
      e = yh - y;
    if(e > PI)
      {
	e -= TPI;
	yh -= TPI;
      }
    if(e < -PI)
      {
	e += TPI;
	yh += TPI;
      }
    }
while(e < 0);

/* Search by simple interval halving.  */
while( (th - tl) > .00001 )
  {
    tm = 0.5 * (tl + th);
    ym = func(tm);
    e = ym - y;
    if(e > PI)
      {
	e -= TPI;
	ym -= TPI;
      }
    if(e < -PI)
      {
	e += TPI;
	ym += TPI;
      }
    if( e > 0 )
      {
	yh = ym;
	th = tm;
      }
    else
      {
	yl = ym;
	tl = tm;
      }
  }
tm = tl + (th - tl) * (y - yl)/(yh - yl);
return (tm);
}

/* Compute desired relation of apperent ecliptic longitude
   as a function of the ephemeris date.  */
double func(t)
double t;
{
  double p[3], q[3], polar[3];
  double s;
#if NEWMOON || FULLMOON
  double m;
#endif

  TDT = t;
  /* Longitude of the sun.  */
  objnum = 0;
  apparent(p,q);
  lonlat(p,TDT,polar,0);
  s = polar[0];
#if NEWMOON || FULLMOON
  /* Longitude of the moon.  */
  objnum = 3;
  apparent(p,q);
  lonlat(p,TDT,polar,0);
  m = polar[0];
  return (s - m);
#endif
#if EQUINOX
  return s;
#endif
}


/* Find apparent coordinates of object at Julian date TDT.
   Q is heliocentric position of object.
   P is geocentric, object minus earth.
   Both outputs are in equatorial rectangular coordinates
   and are referred to the equinox and ecliptic of date.  */

int apparent( p, q )
double p[], q[];
{
double polar[3];
int i;
static double TDTearth = -1.0e38;


/* Calculate heliocentric position of the earth */
if(TDTearth != TDT)
	{
	kepler( TDT, &earth, rearth, eapolar );
	TDTearth = TDT;
	}

if (objnum == 3)
	{
	moonll(TDT, p, polar);
	for(i=0; i<3; i++)
		{
		q[i] = p[i] + rearth[i];
		}
	return 0;
	}
else if( objnum == 0 )
	{
	for(i=0; i<3; i++)
		{
		q[i] = 0.0;
		p[i] = -rearth[i];
		}
	}
else if ((objnum > 0) && (objnum < 10))
	{
	kepler( TDT, &objorb, q, polar );
	}
else
	exit(1);

/* Adjust for light time (planetary aberration)
*/
if( objnum != 0 )
	lightt( &objorb, q, rearth );

/* Find Euclidean vectors between earth, object, and the sun
 */
for( i=0; i<3; i++ )
	p[i] = q[i] - rearth[i];

angles( p, q, rearth );

/* Find unit vector from earth in direction of object
 */
for( i=0; i<3; i++ )
	p[i] /= EO;

/* Correct position for light deflection
 */
if(objnum != 0)
	relativity( p, q, rearth );

/* Correct for annual aberration
 */
annuab( p );

/* Precession of the equinox and ecliptic
 * from J2000.0 to ephemeris date
 */
precess( p, TDT, -1 );

/* Ajust for nutation
 * at current ecliptic.
 */
epsiln( TDT );
nutate( TDT, p );

/* Return dimensions in au.  */
for(i=0; i<3; i++)
	p[i] *= EO;
return 0;
}
