Commit Diff


commit - 95f57b01e21feb457e79eaf52d593422c318024f
commit + cd5bae7871bc0f0bc68b4d2a84703929a7a3c9d1
blob - /dev/null
blob + 3afd07890ec7de5bcd9eb4e7171a4bac7e277bed (mode 644)
--- /dev/null
+++ src/cmd/astro/.cvsignore
@@ -0,0 +1 @@
+o.out
blob - /dev/null
blob + ab3c4119e0028078e7330f24629e4374f496e960 (mode 644)
--- /dev/null
+++ src/cmd/astro/astro.h
@@ -0,0 +1,210 @@
+#include	<u.h>
+#include	<libc.h>
+
+#pragma	varargck	type	"R"	double
+#pragma	varargck	type	"D"	double
+
+typedef	struct	Obj1	Obj1;
+typedef	struct	Obj2	Obj2;
+typedef	struct	Obj3	Obj3;
+typedef	struct	Occ	Occ;
+typedef	struct	Event	Event;
+typedef	struct	Tim	Tim;
+typedef	struct	Moontab	Moontab;
+
+#define	NPTS	12
+#define	PER	1.0
+
+enum
+{
+	DARK	= 1<<0,
+	SIGNIF	= 1<<1,
+	PTIME	= 1<<2,
+	LIGHT	= 1<<3,
+};
+
+struct	Obj1
+{
+	double	ra;
+	double	decl2;
+	double	semi2;
+	double	az;
+	double	el;
+	double	mag;
+};
+struct	Obj2
+{
+	char*	name;
+	char*	name1;
+	void	(*obj)(void);
+	Obj1	point[NPTS+2];
+};
+struct	Obj3
+{
+	double	t1;
+	double	e1;
+	double	t2;
+	double	e2;
+	double	t3;
+	double	e3;
+	double	t4;
+	double	e4;
+	double	t5;
+	double	e5;
+};
+struct Event
+{
+	char*	format;
+	char*	arg1;
+	char*	arg2;
+	double	tim;
+	int	flag;
+};
+struct	Moontab
+{
+	double	f;
+	char	c[4];
+};
+struct	Occ
+{
+	Obj1	act;
+	Obj1	del0;
+	Obj1	del1;
+	Obj1	del2;
+};
+struct	Tim
+{
+	double	ifa[5];
+	char	tz[4];
+};
+
+double	converge;
+
+char	flags[128];
+int	nperiods;
+double	wlong, awlong, nlat, elev;
+double	obliq, phi, eps, tobliq;
+double	dphi, deps;
+double	day, deld, per;
+double	eday, capt, capt2, capt3, gst;
+double	pi, pipi, radian, radsec, deltat;
+double	erad, glat;
+double	xms, yms, zms;
+double	xdot, ydot, zdot;
+
+double	ecc, incl, node, argp, mrad, anom, motion;
+
+double	lambda, beta, rad, mag, semi;
+double	alpha, delta, rp, hp;
+double	ra, decl, semi2;
+double	lha, decl2, lmb2;
+double	az, el;
+
+double	meday, seday, mhp, salph, sdelt, srad;
+
+double*	cafp;
+char*	cacp;
+
+double	rah, ram, ras, dday, dmin, dsec;
+long	sao;
+double	da, dd, px, epoch;
+char	line[100];
+Obj2	osun;
+Obj2	omoon;
+Obj2	oshad;
+Obj2	omerc;
+Obj2	ovenus;
+Obj2	omars;
+Obj2	osat;
+Obj2	ouran;
+Obj2	onept;
+Obj2	oplut;
+Obj2	ojup;
+Obj2	ostar;
+Obj2	ocomet;
+Obj3	occ;
+Obj2*	eobj1;
+Obj2*	eobj2;
+
+char*	startab;
+
+extern	int	dmo[];
+extern	Obj2*	objlst[];
+
+extern	double	venfp[];
+extern	char	vencp[];
+extern	double	sunfp[];
+extern	char	suncp[];
+extern	double	mercfp[];
+extern	char	merccp[];
+extern	double	nutfp[];
+extern	char	nutcp[];
+extern	Moontab moontab[];
+
+extern	void	args(int, char**);
+extern	void	bdtsetup(double, Tim*);
+extern	double	betcross(double);
+extern	double	convdate(Tim*);
+extern	double	cosadd(int, double, ...);
+extern	double	cosx(double, int, int, int, int, double);
+extern	double	dist(Obj1*, Obj1*);
+extern	double	dsrc(double, Tim*, int);
+extern	void	dtsetup(double, Tim*);
+//extern	int	evcomp(void*, void*);
+extern	void	event(char*, char*, char*, double, int);
+extern	void	evflush(void);
+extern	double	fmod(double, double);
+extern	void	fstar(void);
+extern	void	fsun(void);
+extern	void	geo(void);
+extern	void	helio(void);
+extern	void	icosadd(double*, char*);
+extern	void	init(void);
+extern	void	jup(void);
+extern	int	lastsun(Tim*, int);
+extern	int	main(int, char**);
+extern	void	mars(void);
+extern	double	melong(Obj2*);
+extern	void	merc(void);
+extern	void	moon(void);
+extern	void	numb(int);
+extern	void	nutate(void);
+extern	void	occult(Obj2*, Obj2*, double);
+extern	void	output(char*, Obj1*);
+extern	void	pdate(double);
+extern	double	pinorm(double);
+extern	void	ptime(double);
+extern	void	pstime(double);
+extern	double	pyth(double);
+extern	double	readate(void);
+extern	double	readdt(void);
+extern	void	readlat(int);
+extern	double	rise(Obj2*, double);
+extern	int	rline(int);
+extern	void	sat(void);
+extern	void	uran(void);
+extern	void	nept(void);
+extern	void	plut(void);
+extern	void	satel(double);
+extern	void	satels(void);
+extern	void	search(void);
+extern	double	set(Obj2*, double);
+extern	void	set3pt(Obj2*, int, Occ*);
+extern	void	setime(double);
+extern	void	setobj(Obj1*);
+extern	void	setpt(Occ*, double);
+extern	void	shad(void);
+extern	double	sinadd(int, double, ...);
+extern	double	sinx(double, int, int, int, int, double);
+extern	char*	skip(int);
+extern	double	solstice(int);
+extern	void	star(void);
+extern	void	stars(void);
+extern	void	sun(void);
+extern	double	sunel(double);
+extern	void	venus(void);
+extern	int	vis(double, double, double, double);
+extern	void	comet(void);
+extern	int	Rconv(Fmt*);
+extern	int	Dconv(Fmt*);
+extern	double	etdate(long, int, double);
blob - /dev/null
blob + bfd11dc08ebc50baaa97c9d5fd5e4004a069a7cb (mode 644)
--- /dev/null
+++ src/cmd/astro/comet.c
@@ -0,0 +1,132 @@
+#include "astro.h"
+
+#define	MAXE	(.999)	/* cant do hyperbolas */
+
+void
+comet(void)
+{
+	double pturbl, pturbb, pturbr;
+	double lograd;
+	double dele, enom, vnom, nd, sl;
+
+	struct	elem
+	{
+		double	t;	/* time of perihelion */
+		double	q;	/* perihelion distance */
+		double	e;	/* eccentricity */
+		double	i;	/* inclination */
+		double	w;	/* argument of perihelion */
+		double	o;	/* longitude of ascending node */
+	} elem;
+
+/*	elem = (struct elem)
+	{
+		etdate(1990, 5, 19.293),
+		0.9362731,
+		0.6940149,
+		11.41096,
+		198.77059,
+		69.27130,
+	};	/* p/schwassmann-wachmann 3, 1989d */
+/*	elem = (struct elem)
+	{
+		etdate(1990, 4, 9.9761),
+		0.349957,
+		1.00038,
+		58.9596,
+		61.5546,
+		75.2132,
+	};	/* austin 3, 1989c */
+/*	elem = (struct elem)
+	{
+		etdate(1990, 10, 24.36),
+		0.9385,
+		1.00038,
+		131.62,
+		242.58,
+		138.57,
+	};	/* levy 6 , 1990c */
+/*	elem=(struct elem)
+	{
+		etdate(1996, 5, 1.3965),
+		0.230035,
+		0.999662,
+		124.9098,
+		130.2102,
+		188.0430,
+	};	/* C/1996 B2 (Hyakutake) */
+/*	elem=(struct elem)
+	{
+		etdate(1997, 4, 1.13413),
+		0.9141047,
+		0.9950989,
+		89.42932,
+		130.59066,
+		282.47069,
+	};	/*C/1995 O1 (Hale-Bopp) */
+/*	elem=(struct elem)
+	{
+		etdate(2000, 7, 26.1754),
+		0.765126,
+		0.999356,
+		149.3904,
+		151.0510,
+		83.1909,
+	};	/*C/1999 S4 (Linear) */
+	elem=(struct elem)
+	{
+		etdate(2002, 3, 18.9784),
+		0.5070601,
+		0.990111,
+		28.12106,
+		34.6666,
+		93.1206,
+	};	/*C/2002 C1 (Ikeya-Zhang) */
+
+	ecc = elem.e;
+	if(ecc > MAXE)
+		ecc = MAXE;
+	incl = elem.i * radian;
+	node = (elem.o + 0.4593) * radian;
+	argp = (elem.w + elem.o + 0.4066) * radian;
+	mrad = elem.q / (1-ecc);
+        motion = .01720209895 * sqrt(1/(mrad*mrad*mrad))/radian;
+	anom = (eday - (elem.t - 2415020)) * motion * radian;
+	enom = anom + ecc*sin(anom);
+
+	do {
+		dele = (anom - enom + ecc * sin(enom)) /
+			(1 - ecc*cos(enom));
+		enom += dele;
+	} while(fabs(dele) > converge);
+
+	vnom = 2*atan2(
+		sqrt((1+ecc)/(1-ecc))*sin(enom/2),
+		cos(enom/2));
+	rad = mrad*(1-ecc*cos(enom));
+	lambda = vnom + argp;
+	pturbl = 0;
+	lambda += pturbl*radsec;
+	pturbb = 0;
+	pturbr = 0;
+
+/*
+ *	reduce to the ecliptic
+ */
+	nd = lambda - node;
+	lambda = node + atan2(sin(nd)*cos(incl),cos(nd));
+
+	sl = sin(incl)*sin(nd) + pturbb*radsec;
+	beta = atan2(sl, sqrt(1-sl*sl));
+
+	lograd = pturbr*2.30258509;
+	rad *= 1 + lograd;
+
+	motion *= radian*mrad*mrad/(rad*rad);
+	semi = 0;
+
+	mag = 5.47 + 6.1/2.303*log(rad);
+
+	helio();
+	geo();
+}
blob - /dev/null
blob + a632149a03c02686bfef681e5926d3277fedb01f (mode 644)
--- /dev/null
+++ src/cmd/astro/cosadd.c
@@ -0,0 +1,64 @@
+#include "astro.h"
+
+
+void
+icosadd(double *fp, char *cp)
+{
+
+	cafp = fp;
+	cacp = cp;
+}
+
+double
+cosadd(int n, double coef, ...)
+{
+	double *coefp;
+	char *cp;
+	int i;
+	double sum, a1, a2;
+
+	sum = 0;
+	cp = cacp;
+
+loop:
+	a1 = *cafp++;
+	if(a1 == 0) {
+		cacp = cp;
+		return sum;
+	}
+	a2 = *cafp++;
+	i = n;
+	coefp = &coef;
+	do
+		a2 += *cp++ * *coefp++;
+	while(--i);
+	sum += a1 * cos(a2);
+	goto loop;
+}
+
+double
+sinadd(int n, double coef, ...)
+{
+	double *coefp;
+	char *cp;
+	int i;
+	double sum, a1, a2;
+
+	sum = 0;
+	cp = cacp;
+
+loop:
+	a1 = *cafp++;
+	if(a1 == 0) {
+		cacp = cp;
+		return sum;
+	}
+	a2 = *cafp++;
+	i = n;
+	coefp = &coef;
+	do
+		a2 += *cp++ * *coefp++;
+	while(--i);
+	sum += a1 * sin(a2);
+	goto loop;
+}
blob - /dev/null
blob + 3aec8752da27fd42ab9d4ea0c95e79dbd05d23e9 (mode 644)
--- /dev/null
+++ src/cmd/astro/dist.c
@@ -0,0 +1,263 @@
+#include "astro.h"
+
+double
+dist(Obj1 *p, Obj1 *q)
+{
+	double a;
+
+	a = sin(p->decl2)*sin(q->decl2) +
+		cos(p->decl2)*cos(q->decl2)*cos(p->ra-q->ra);
+	a = fabs(atan2(pyth(a), a)) / radsec;
+	return a;
+}
+
+int
+rline(int f)
+{
+	char *p;
+	int c;
+	static char buf[1024];
+	static int bc, bn, bf;
+
+	if(bf != f) {
+		bf = f;
+		bn = 0;
+	}
+	p = line;
+	do {
+		if(bn <= 0) {
+			bn = read(bf, buf, sizeof(buf));
+			if(bn <= 0)
+				return 1;
+			bc = 0;
+		}
+		c = buf[bc];
+		bn--; bc++;
+		*p++ = c;
+	} while(c != '\n');
+	return 0;
+}
+
+double
+sunel(double t)
+{
+	int i;
+
+	i = floor(t);
+	if(i < 0 || i > NPTS+1)
+		return -90;
+	t = osun.point[i].el +
+		(t-i)*(osun.point[i+1].el - osun.point[i].el);
+	return t;
+}
+
+double
+rise(Obj2 *op, double el)
+{
+	Obj2 *p;
+	int i;
+	double e1, e2;
+
+	e2 = 0;
+	p = op;
+	for(i=0; i<=NPTS; i++) {
+		e1 = e2;
+		e2 = p->point[i].el;
+		if(i >= 1 && e1 <= el && e2 > el)
+			goto found;
+	}
+	return -1;
+
+found:
+	return i - 1 + (el-e1)/(e2-e1);
+}
+
+double
+set(Obj2 *op, double el)
+{
+	Obj2 *p;
+	int i;
+	double e1, e2;
+
+	e2 = 0;
+	p = op;
+	for(i=0; i<=NPTS; i++) {
+		e1 = e2;
+		e2 = p->point[i].el;
+		if(i >= 1 && e1 > el && e2 <= el)
+			goto found;
+	}
+	return -1;
+
+found:
+	return i - 1 + (el-e1)/(e2-e1);
+}
+
+double
+solstice(int n)
+{
+	int i;
+	double d1, d2, d3;
+
+	d3 = (n*pi)/2 - pi;
+	if(n == 0)
+		d3 += pi;
+	d2 = 0.;
+	for(i=0; i<=NPTS; i++) {
+		d1 = d2;
+		d2 = osun.point[i].ra;
+		if(n == 0) {
+			d2 -= pi;
+			if(d2 < -pi)
+				d2 += pipi;
+		}
+		if(i >= 1 && d3 >= d1 && d3 < d2)
+			goto found;
+	}
+	return -1;
+
+found:
+	return i - (d3-d2)/(d1-d2);
+}
+
+double
+betcross(double b)
+{
+	int i;
+	double d1, d2;
+
+	d2 = 0;
+	for(i=0; i<=NPTS; i++) {
+		d1 = d2;
+		d2 = osun.point[i].mag;
+		if(i >= 1 && b >= d1 && b < d2)
+			goto found;
+	}
+	return -1;
+
+found:
+	return i - (b-d2)/(d1-d2);
+}
+
+double
+melong(Obj2 *op)
+{
+	Obj2 *p;
+	int i;
+	double d1, d2, d3;
+
+	d2 = 0;
+	d3 = 0;
+	p = op;
+	for(i=0; i<=NPTS; i++) {
+		d1 = d2;
+		d2 = d3;
+		d3 = dist(&p->point[i], &osun.point[i]);
+		if(i >= 2 && d2 >= d1 && d2 >= d3)
+			goto found;
+	}
+	return -1;
+
+found:
+	return i - 2;
+}
+
+#define	NEVENT	100
+Event	events[NEVENT];
+Event*	eventp = 0;
+
+void
+event(char *format, char *arg1, char *arg2, double tim, int flag)
+{
+	Event *p;
+
+	if(flag & DARK)
+		if(sunel(tim) > -12)
+			return;
+	if(flag & LIGHT)
+		if(sunel(tim) < 0)
+			return;
+	if(eventp == 0)
+		eventp = events;
+	p = eventp;
+	if(p >= events+NEVENT) {
+		fprint(2, "too many events\n");
+		return;
+	}
+	eventp++;
+	p->format = format;
+	p->arg1 = arg1;
+	p->arg2 = arg2;
+	p->tim = tim;
+	p->flag = flag;
+}
+
+int	evcomp();
+
+void
+evflush(void)
+{
+	Event *p;
+
+	if(eventp == 0)
+		return;
+	qsort(events, eventp-events, sizeof *p, evcomp);
+	for(p = events; p<eventp; p++) {
+		if((p->flag&SIGNIF) && flags['s'])
+			print("ding ding ding ");
+		print(p->format, p->arg1, p->arg2);
+		if(p->flag & PTIME)
+			ptime(day + p->tim*deld);
+		print("\n");
+	}
+	eventp = 0;
+}
+
+int
+evcomp(void *a1, void *a2)
+{
+	double t1, t2;
+	Event *p1, *p2;
+
+	p1 = a1;
+	p2 = a2;
+	t1 = p1->tim;
+	t2 = p2->tim;
+	if(p1->flag & SIGNIF)
+		t1 -= 1000.;
+	if(p2->flag & SIGNIF)
+		t2 -= 1000.;
+	if(t1 > t2)
+		return 1;
+	if(t2 > t1)
+		return -1;
+	return 0;
+}
+
+double
+pyth(double x)
+{
+
+	x *= x;
+	if(x > 1)
+		x = 1;
+	return sqrt(1-x);
+}
+
+char*
+skip(int n)
+{
+	int i;
+	char *cp;
+
+	cp = line;
+	for(i=0; i<n; i++) {
+		while(*cp == ' ' || *cp == '\t')
+			cp++;
+		while(*cp != '\n' && *cp != ' ' && *cp != '\t')
+			cp++;
+	}
+	while(*cp == ' ' || *cp == '\t')
+		cp++;
+	return cp;
+}
blob - /dev/null
blob + de562210d82bb65744e8cbf91760d6f068960c7c (mode 644)
--- /dev/null
+++ src/cmd/astro/geo.c
@@ -0,0 +1,60 @@
+#include "astro.h"
+
+void
+geo(void)
+{
+
+/*
+ *	uses alpha, delta, rp
+ */
+
+/*
+ *	sets ra, decl, lha, decl2, az, el
+ */
+
+/*
+ *	geo converts geocentric equatorial coordinates
+ *	to topocentric equatorial and topocentric horizon
+ *	coordinates.
+ *	All are (usually) referred to the true equator.
+ */
+
+	double sel, saz, caz;
+	double f;
+	double sa, ca, sd;
+
+/*
+ *	convert to local hour angle and declination
+ */
+
+	lha = gst - alpha - wlong;
+	decl = delta;
+
+/*
+ *	compute diurnal parallax (requires geocentric latitude)
+ */
+
+	sa = cos(decl)*sin(lha);
+	ca = cos(decl)*cos(lha) - erad*cos(glat)*sin(hp);
+	sd = sin(decl)           - erad*sin(glat)*sin(hp);
+
+	lha = atan2(sa, ca);
+	decl2 = atan2(sd, sqrt(sa*sa+ca*ca));
+	f = sqrt(sa*sa+ca*ca+sd*sd);
+	semi2 = semi/f;
+	ra = gst - lha - wlong;
+	ra = pinorm(ra);
+
+/*
+ *	convert to horizon coordinates
+ */
+
+	sel = sin(nlat)*sin(decl2) + cos(nlat)*cos(decl2)*cos(lha);
+	el = atan2(sel, pyth(sel));
+	saz = sin(lha)*cos(decl2);
+	caz = cos(nlat)*sin(decl2) - sin(nlat)*cos(decl2)*cos(lha);
+	az = pi + atan2(saz, -caz);
+
+	az /= radian;
+	el /= radian;
+}
blob - /dev/null
blob + cb41578639221bb8d9004958464fdb1db75447d3 (mode 644)
--- /dev/null
+++ src/cmd/astro/helio.c
@@ -0,0 +1,81 @@
+#include "astro.h"
+
+void
+helio(void)
+{
+/*
+ *	uses lambda, beta, rad, motion
+ *	sets alpha, delta, rp
+ */
+
+/*
+ *	helio converts from ecliptic heliocentric coordinates
+ *	referred to the mean equinox of date
+ *	to equatorial geocentric coordinates referred to
+ *	the true equator and equinox
+ */
+
+	double xmp, ymp, zmp;
+	double beta2;
+
+/*
+ *	compute geocentric distance of object and
+ *	compute light-time correction (i.i. planetary aberration)
+ */
+
+	xmp = rad*cos(beta)*cos(lambda);
+	ymp = rad*cos(beta)*sin(lambda);
+	zmp = rad*sin(beta);
+	rp = sqrt((xmp+xms)*(xmp+xms) +
+		(ymp+yms)*(ymp+yms) +
+		(zmp+zms)*(zmp+zms));
+	lmb2 = lambda - .0057756e0*rp*motion;
+
+	xmp = rad*cos(beta)*cos(lmb2);
+	ymp = rad*cos(beta)*sin(lmb2);
+	zmp = rad*sin(beta);
+
+/*
+ *	compute annual parallax from the position of the sun
+ */
+
+	xmp += xms;
+	ymp += yms;
+	zmp += zms;
+	rp = sqrt(xmp*xmp + ymp*ymp + zmp*zmp);
+
+/*
+ *	compute annual (i.e. stellar) aberration
+ *	from the orbital velocity of the earth
+ *	(by an incorrect method)
+ */
+
+	xmp -= xdot*rp;
+	ymp -= ydot*rp;
+	zmp -= zdot*rp;
+
+/*
+ *	perform the nutation and so convert from the mean
+ *	equator and equinox to the true
+ */
+
+	lmb2 = atan2(ymp, xmp);
+	beta2 = atan2(zmp, sqrt(xmp*xmp+ymp*ymp));
+	lmb2 += phi;
+
+/*
+ *	change to equatorial coordinates
+ */
+
+	xmp = rp*cos(lmb2)*cos(beta2);
+	ymp = rp*(sin(lmb2)*cos(beta2)*cos(tobliq) - sin(tobliq)*sin(beta2));
+	zmp = rp*(sin(lmb2)*cos(beta2)*sin(tobliq) + cos(tobliq)*sin(beta2));
+
+	alpha = atan2(ymp, xmp);
+	delta = atan2(zmp, sqrt(xmp*xmp+ymp*ymp));
+
+	hp = 8.794e0*radsec/rp;
+	semi /= rp;
+	if(rad > 0 && rad < 2.e5)
+		mag += 2.17*log(rad*rp);
+}
blob - /dev/null
blob + f376f665f70af3c84e0e4f8b8af57ca3406df2e0 (mode 644)
--- /dev/null
+++ src/cmd/astro/init.c
@@ -0,0 +1,149 @@
+#include "astro.h"
+
+Obj2*	objlst[] =
+{
+	&osun,
+	&omoon,
+	&oshad,
+	&omerc,
+	&ovenus,
+	&omars,
+	&ojup,
+	&osat,
+	&ouran,
+	&onept,
+	&oplut,
+	&ocomet,
+	0,
+};
+
+struct	idata
+{
+	char*	name;
+	char*	name1;
+	void	(*obj)(void);
+} idata[] =
+{
+	"The sun",	"sun",		fsun,
+	"The moon",	"moon",		moon,
+	"The shadow",	"shadow",	shad,
+	"Mercury",	"mercury",	merc,
+	"Venus",	"venus",	venus,
+	"Mars",		"mars",		mars,
+	"Jupiter",	"jupiter",	jup,
+	"Saturn",	"saturn",	sat,
+	"Uranus",	"uranus",	uran,
+	"Neptune",	"neptune",	nept,
+	"Pluto",	"pluto",	plut,
+	"Comet",	"comet",	comet,
+};
+
+void
+init(void)
+{
+	Obj2 *q;
+	int i;
+
+	glat = nlat - (692.74*radsec)*sin(2.*nlat)
+		 + (1.16*radsec)*sin(4.*nlat);
+	erad = .99832707e0 + .00167644e0*cos(2.*nlat)
+		 - 0.352e-5*cos(4.*nlat)
+		 + 0.001e-5*cos(6.*nlat)
+		 + 0.1568e-6*elev;
+
+	for(i=0; q=objlst[i]; i++) {
+		q->name = idata[i].name;
+		q->name1 = idata[i].name1;
+		q->obj = idata[i].obj;
+	}
+	ostar.obj = fstar;
+	ostar.name = "star";
+}
+
+void
+setime(double d)
+{
+	double x, xm, ym, zm;
+
+	eday = d + deltat/86400.;
+	wlong = awlong + 15.*deltat*radsec;
+
+	capt = eday/36524.220e0;
+	capt2 = capt*capt;
+	capt3 = capt*capt2;
+	nutate();
+	eday += .1;
+	sun();
+	srad = rad;
+	xm = rad*cos(beta)*cos(lambda);
+	ym = rad*cos(beta)*sin(lambda);
+	zm = rad*sin(beta);
+	eday -= .1;
+	sun();
+	xms = rad*cos(beta)*cos(lambda);
+	yms = rad*cos(beta)*sin(lambda);
+	zms = rad*sin(beta);
+	x = .057756;
+	xdot = x*(xm-xms);
+	ydot = x*(ym-yms);
+	zdot = x*(zm-zms);
+}
+
+void
+setobj(Obj1 *op)
+{
+	Obj1 *p;
+
+	p = op;
+	p->ra = ra;
+	p->decl2 = decl2;
+	p->semi2 = semi2;
+	p->az = az;
+	p->el = el;
+	p->mag = mag;
+}
+
+long	starsao = 0;
+
+void
+fstar(void)
+{
+
+	ra = ostar.point[0].ra;
+	decl2 = ostar.point[0].decl2;
+	semi2 = ostar.point[0].semi2;
+	az = ostar.point[0].az;
+	el = ostar.point[0].el;
+	mag = ostar.point[0].mag;
+}
+
+void
+fsun(void)
+{
+
+	beta = 0;
+	rad = 0;
+	lambda = 0;
+	motion = 0;
+	helio();
+	geo();
+	seday = eday;
+	salph = alpha;
+	sdelt = delta;
+	mag = lmb2;
+}
+
+void
+shad(void)
+{
+
+	if(seday != eday)
+		fsun();
+	if(meday != eday)
+		moon();
+	alpha = fmod(salph+pi, pipi);
+	delta = -sdelt;
+	hp = mhp;
+	semi = 1.0183*mhp/radsec - 969.85/srad;
+	geo();
+}
blob - /dev/null
blob + a3353382aeebfb5cf1a7fbe72781ecb699f4b284 (mode 644)
--- /dev/null
+++ src/cmd/astro/jup.c
@@ -0,0 +1,68 @@
+#include "astro.h"
+
+void
+jup(void)
+{
+	double pturbl, pturbb, pturbr;
+	double lograd;
+	double dele, enom, vnom, nd, sl;
+
+
+	ecc = .0483376 + 163.e-6*capt;
+	incl = 1.308660 - .0055*capt;
+	node = 99.43785 + 1.011*capt;
+	argp = 12.71165 + 1.611*capt;
+	mrad = 5.202803;
+	anom = 225.22165 + .0830912*eday - .0484*capt;
+	motion = 299.1284/3600.;
+
+
+	anom = anom;
+	incl *= radian;
+	node *= radian;
+	argp *= radian;
+	anom = fmod(anom,360.)*radian;
+
+	enom = anom + ecc*sin(anom);
+	do {
+		dele = (anom - enom + ecc * sin(enom)) /
+			(1. - ecc*cos(enom));
+		enom += dele;
+	} while(fabs(dele) > converge);
+	vnom = 2.*atan2(sqrt((1.+ecc)/(1.-ecc))*sin(enom/2.),
+		cos(enom/2.));
+	rad = mrad*(1. - ecc*cos(enom));
+
+	lambda = vnom + argp;
+
+	pturbl = 0.;
+
+	lambda += pturbl*radsec;
+
+	pturbb = 0.;
+
+	pturbr = 0.;
+
+/*
+ *	reduce to the ecliptic
+ */
+
+	nd = lambda - node;
+	lambda = node + atan2(sin(nd)*cos(incl),cos(nd));
+
+	sl = sin(incl)*sin(nd) + pturbb*radsec;
+	beta = atan2(sl, pyth(sl));
+
+	lograd = pturbr*2.30258509;
+	rad *= 1. + lograd;
+
+
+	lambda += 555.*radsec;
+	beta -= 51.*radsec;
+	motion *= radian*mrad*mrad/(rad*rad);
+	semi = 98.47;
+
+	mag = -8.93;
+	helio();
+	geo();
+}
blob - /dev/null
blob + 687695c878db329fe0839066761200545624ae9f (mode 644)
--- /dev/null
+++ src/cmd/astro/main.c
@@ -0,0 +1,223 @@
+#include "astro.h"
+
+char*	herefile = SYS9 "/lib/sky/here";
+
+int
+main(int argc, char *argv[])
+{
+	int i, j;
+	double d;
+
+	pi = atan(1.0)*4;
+	pipi = pi*2;
+	radian = pi/180;
+	radsec = radian/3600;
+	converge = 1.0e-14;
+
+	fmtinstall('R', Rconv);
+	fmtinstall('D', Dconv);
+
+	per = PER;
+	deld = PER/NPTS;
+	init();
+	args(argc, argv);
+	init();
+
+loop:
+	d = day;
+	pdate(d);
+	if(flags['p'] || flags['e']) {
+		print(" ");
+		ptime(d);
+		pstime(d);
+	}
+	print("\n");
+	for(i=0; i<=NPTS+1; i++) {
+		setime(d);
+
+		for(j=0; objlst[j]; j++) {
+			(*objlst[j]->obj)();
+			setobj(&objlst[j]->point[i]);
+			if(flags['p']) {
+				if(flags['m'])
+					if(strcmp(objlst[j]->name, "Comet"))
+						continue;
+				output(objlst[j]->name, &objlst[j]->point[i]);
+			}
+		}
+		if(flags['e']) {
+			d = dist(&eobj1->point[i], &eobj2->point[i]);
+			print("dist %s to %s = %.4f\n", eobj1->name, eobj2->name, d);
+		}
+//		if(flags['p']) {
+//			pdate(d);
+//			print(" ");
+//			ptime(d);
+//			print("\n");
+//		}
+		if(flags['p'] || flags['e'])
+			break;
+		d += deld;
+	}
+	if(!(flags['p'] || flags['e']))
+		search();
+	day += per;
+	nperiods -= 1;
+	if(nperiods > 0)
+		goto loop;
+	exits(0);
+	return 0;		/* gcc */
+}
+
+void
+args(int argc, char *argv[])
+{
+	char *p;
+	long t;
+	int f, i;
+	Obj2 *q;
+
+	memset(flags, 0, sizeof(flags));
+	ARGBEGIN {
+	default:
+		fprint(2, "astro [-adeklmopst] [-c nperiod] [-C tperiod]\n");
+		exits(0);
+
+	case 'c':
+		nperiods = 1;
+		p = ARGF();
+		if(p)
+			nperiods = atol(p);
+		flags['c']++;
+		break;
+	case 'C':
+		p = ARGF();
+		if(p)
+			per = atof(p);
+		break;
+	case 'e':
+		eobj1 = nil;
+		eobj2 = nil;
+		p = ARGF();
+		if(p) {
+			for(i=0; q=objlst[i]; i++) {
+				if(strcmp(q->name, p) == 0)
+					eobj1 = q;
+				if(strcmp(q->name1, p) == 0)
+					eobj1 = q;
+			}
+			p = ARGF();
+			if(p) {
+				for(i=0; q=objlst[i]; i++) {
+					if(strcmp(q->name, p) == 0)
+						eobj2 = q;
+					if(strcmp(q->name1, p) == 0)
+						eobj2 = q;
+				}
+			}
+		}
+		if(eobj1 && eobj2) {
+			flags['e']++;
+			break;
+		}
+		fprint(2, "cant recognize eclipse objects\n");
+		exits("eflag");
+
+	case 'a':
+	case 'd':
+	case 'j':
+	case 'k':
+	case 'l':
+	case 'm':
+	case 'o':
+	case 'p':
+	case 's':
+	case 't':
+		flags[ARGC()]++;
+		break;
+	} ARGEND
+	if(*argv){
+		fprint(2, "usage: astro [-dlpsatokm] [-c nday] [-e obj1 obj2]\n");
+		exits("usage");
+	}
+
+	t = time(0);
+	day = t/86400. + 25567.5;
+	if(flags['d'])
+		day = readate();
+	if(flags['j'])
+		print("jday = %.4f\n", day);
+	deltat = day * .001704;
+	if(deltat > 32.184)		// assume date is utc1
+		deltat = 32.184;	// correct by leap sec
+	if(flags['t'])
+		deltat = readdt();
+
+	if(flags['l']) {
+		fprint(2, "nlat wlong elev\n");
+		readlat(0);
+	} else {
+		f = open(herefile, OREAD);
+		if(f < 0) {
+			fprint(2, "%s?\n", herefile);
+			/* btl mh */
+			nlat = (40 + 41.06/60)*radian;
+			awlong = (74 + 23.98/60)*radian;
+			elev = 150 * 3.28084;
+		} else {
+			readlat(f);
+			close(f);
+		}
+	}
+}
+
+double
+readate(void)
+{
+	int i;
+	Tim t;
+
+	fprint(2, "year mo da hr min\n");
+	rline(0);
+	for(i=0; i<5; i++)
+		t.ifa[i] = atof(skip(i));
+	return convdate(&t);
+}
+
+double
+readdt(void)
+{
+
+	fprint(2, "ΔT (sec) (%.3f)\n", deltat);
+	rline(0);
+	return atof(skip(0));
+}
+
+double
+etdate(long year, int mo, double day)
+{
+	Tim t;
+
+	t.ifa[0] = year;
+	t.ifa[1] = mo;
+	t.ifa[2] = day;
+	t.ifa[3] = 0;
+	t.ifa[4] = 0;
+	return convdate(&t) + 2415020;
+}
+
+void
+readlat(int f)
+{
+
+	rline(f);
+	nlat = atof(skip(0)) * radian;
+	awlong = atof(skip(1)) * radian;
+	elev = atof(skip(2)) * 3.28084;
+}
+
+double
+fmod(double a, double b)
+{
+	return a - floor(a/b)*b;
+}
blob - /dev/null
blob + 327ab8d2276a51e1731ab9bf007e1f46a1b4a900 (mode 644)
--- /dev/null
+++ src/cmd/astro/mars.c
@@ -0,0 +1,67 @@
+#include "astro.h"
+
+void
+mars(void)
+{
+	double pturbl, pturbb, pturbr;
+	double lograd;
+	double dele, enom, vnom, nd, sl;
+	double lsun, elong, ci, dlong;
+
+
+	ecc = .09331290 + .000092064*capt;
+	incl = 1.850333 - 6.75e-4*capt;
+	node = 48.786442 + .770992*capt;
+	argp = 334.218203 + 1.840758*capt + 1.30e-4*capt2;
+	mrad = 1.5236915;
+	anom = 319.529425 + .5240207666*eday + 1.808e-4*capt2;
+	motion = 0.5240711638;
+
+
+	incl = incl*radian;
+	node = node*radian;
+	argp = argp*radian;
+	anom = fmod(anom,360.)*radian;
+
+	enom = anom + ecc*sin(anom);
+	do {
+		dele = (anom - enom + ecc * sin(enom)) /
+			(1. - ecc*cos(enom));
+		enom += dele;
+	} while(fabs(dele) > converge);
+	vnom = 2.*atan2(sqrt((1.+ecc)/(1.-ecc))*sin(enom/2.),cos(enom/2.));
+	rad = mrad*(1. - ecc*cos(enom));
+
+	lambda = vnom + argp;
+	pturbl = 0.;
+	lambda = lambda + pturbl*radsec;
+	pturbb = 0.;
+	pturbr = 0.;
+
+/*
+ *	reduce to the ecliptic
+ */
+
+	nd = lambda - node;
+	lambda = node + atan2(sin(nd)*cos(incl),cos(nd));
+
+	sl = sin(incl)*sin(nd) + pturbb*radsec;
+	beta = atan2(sl, pyth(sl));
+
+	lograd = pturbr*2.30258509;
+	rad *= 1. + lograd;
+
+
+	motion *= radian*mrad*mrad/(rad*rad);
+	semi = 4.68;
+
+	lsun = 99.696678 + 0.9856473354*eday;
+	lsun *= radian;
+	elong = lambda - lsun;
+	ci = (rad - cos(elong))/sqrt(1. + rad*rad - 2.*rad*cos(elong));
+	dlong = atan2(pyth(ci), ci)/radian;
+	mag = -1.30 + .01486*dlong;
+
+	helio();
+	geo();
+}
blob - /dev/null
blob + 4877ef2e10aa6140c64656961298d5ad2d3d35ed (mode 644)
--- /dev/null
+++ src/cmd/astro/merc.c
@@ -0,0 +1,84 @@
+#include "astro.h"
+
+void
+merc(void)
+{
+	double pturbl, pturbr;
+	double lograd;
+	double dele, enom, vnom, nd, sl;
+	double q0, v0, t0, j0 , s0;
+	double lsun, elong, ci, dlong;
+
+	ecc = .20561421 + .00002046*capt - 0.03e-6*capt2;
+	incl = 7.0028806 + .0018608*capt - 18.3e-6*capt2;
+	node = 47.145944 + 1.185208*capt + .0001739*capt2;
+	argp = 75.899697 + 1.555490*capt + .0002947*capt2;
+	mrad = .3870986;
+	anom = 102.279381 + 4.0923344364*eday + 6.7e-6*capt2;
+	motion = 4.0923770233;
+
+	q0 = 102.28  + 4.092334429*eday;
+	v0 = 212.536 + 1.602126105*eday;
+	t0 = -1.45  + .985604737*eday;
+	j0 = 225.36 + .083086735*eday;
+	s0 = 175.68 + .033455441*eday;
+
+	q0 *= radian;
+	v0 *= radian;
+	t0 *= radian;
+	j0 *= radian;
+	s0 *= radian;
+
+	incl *= radian;
+	node *= radian;
+	argp *= radian;
+	anom = fmod(anom, 360.)*radian;
+
+
+	enom = anom + ecc*sin(anom);
+	do {
+		dele = (anom - enom + ecc * sin(enom)) /
+			(1. - ecc*cos(enom));
+		enom += dele;
+	} while(fabs(dele) > converge);
+	vnom = 2.*atan2(sqrt((1.+ecc)/(1.-ecc))*sin(enom/2.),
+			cos(enom/2.));
+	rad = mrad*(1. - ecc*cos(enom));
+
+	icosadd(mercfp, merccp);
+	pturbl =  cosadd(2, q0, -v0);
+	pturbl += cosadd(2, q0, -t0);
+	pturbl += cosadd(2, q0, -j0);
+	pturbl += cosadd(2, q0, -s0);
+
+	pturbr =  cosadd(2, q0, -v0);
+	pturbr += cosadd(2, q0, -t0);
+	pturbr += cosadd(2, q0, -j0);
+
+/*
+ *	reduce to the ecliptic
+ */
+
+	lambda = vnom + argp + pturbl*radsec;
+	nd = lambda - node;
+	lambda = node + atan2(sin(nd)*cos(incl), cos(nd));
+
+	sl = sin(incl)*sin(nd);
+	beta = atan2(sl, pyth(sl));
+
+	lograd = pturbr*2.30258509;
+	rad *= 1. + lograd;
+
+	motion *= radian*mrad*mrad/(rad*rad);
+	semi = 3.34;
+
+	lsun = 99.696678 + 0.9856473354*eday;
+	lsun *= radian;
+	elong = lambda - lsun;
+	ci = (rad - cos(elong))/sqrt(1. + rad*rad - 2.*rad*cos(elong));
+	dlong = atan2(pyth(ci), ci)/radian;
+	mag = -.003 + .01815*dlong + .0001023*dlong*dlong;
+
+	helio();
+	geo();
+}
blob - /dev/null
blob + ebe1f0ec73971c99324d20dc48b1ff4624c37989 (mode 644)
--- /dev/null
+++ src/cmd/astro/merct.c
@@ -0,0 +1,336 @@
+#include "astro.h"
+
+double	mercfp[] =
+{
+	0.013,		0.6807,
+	0.048,		0.6283,
+	0.185,		0.6231,
+	0.711,		0.6191,
+	0.285,		0.5784,
+	0.075,		0.5411,
+	0.019,		0.5585,
+	0.010,		2.8449,
+	0.039,		2.8117,
+	0.147,		2.8135,
+	0.552,		2.8126,
+	2.100,		2.8126,
+	3.724,		2.8046,
+	0.729,		2.7883,
+	0.186,		2.7890,
+	0.049,		2.7943,
+	0.013,		2.7402,
+	0.033,		1.8361,
+	0.118,		1.8396,
+	0.431,		1.8391,
+	1.329,		1.8288,
+	0.539,		4.8686,
+	0.111,		4.8904,
+	0.027,		4.8956,
+	0.012,		3.9794,
+	0.056,		3.9636,
+	0.294,		3.9910,
+	0.484,		3.9514,
+	0.070,		3.9270,
+	0.018,		3.9270,
+	0.013,		6.1261,
+	0.050,		6.1052,
+	0.185,		6.1069,
+	0.685,		6.1011,
+	2.810,		6.1062,
+	7.356,		6.0699,
+	1.471,		6.0685,
+	0.375,		6.0687,
+	0.098,		6.0720,
+	0.026,		6.0476,
+	0.062,		5.1540,
+	0.122,		5.1191,
+	0.011,		0.9076,
+	0.074,		1.0123,
+	0.106,		0.9372,
+	0.017,		0.9425,
+	0.020,		0.0506,
+	0.052,		0.0384,
+	0.052,		3.0281,
+	0.012,		3.0543,
+	0.011,		2.1642,
+	0.016,		2.2340,
+	0.040,		4.3912,
+	0.080,		4.4262,
+	0.016,		4.4506,
+	0,
+
+	0.014,		1.0996,
+	0.056,		1.1153,
+	0.219,		1.1160,
+	0.083,		1.0734,
+	0.024,		0.9442,
+	0.018,		3.8432,
+	0.070,		3.8293,
+	0.256,		3.8230,
+	0.443,		3.8132,
+	0.080,		3.7647,
+	0.020,		3.7734,
+	0.019,		0.0000,
+	0.133,		0.1134,
+	0.129,		6.2588,
+	0.026,		6.2413,
+	0.026,		2.6599,
+	0.087,		2.6232,
+	0.374,		2.6496,
+	0.808,		2.5470,
+	0.129,		2.5587,
+	0.019,		2.5534,
+	0.012,		2.1642,
+	0,
+
+	0.014,		3.1416,
+	0.047,		3.1625,
+	0.179,		3.1695,
+	0.697,		3.1603,
+	0.574,		4.1315,
+	0.181,		4.2537,
+	0.047,		4.2481,
+	0.013,		4.2062,
+	0.018,		0.6650,
+	0.069,		0.6405,
+	0.253,		0.6449,
+	0.938,		0.6454,
+	3.275,		0.6458,
+	0.499,		0.5569,
+	0.119,		0.5271,
+	0.032,		0.5184,
+	0.030,		0.4939,
+	0.106,		0.4171,
+	0.353,		0.4510,
+	0.056,		0.3840,
+	0.013,		0.3142,
+	0.028,		0.2531,
+	0,
+
+	0.034,		0.9512,
+	0.060,		4.7962,
+	0.028,		4.7124,
+	0.028,		4.1836,
+	0.102,		4.1871,
+	0.380,		4.1864,
+	0.059,		4.1818,
+	0.015,		4.2185,
+	0.012,		4.1713,
+	0.050,		4.1870,
+	0,
+
+	0.218e-6,	5.3369,
+	0.491e-6,	5.3281,
+	0.172e-6,	2.1642,
+	0.091e-6,	2.1084,
+	0.204e-6,	1.2460,
+	0.712e-6,	1.2413,
+	2.370e-6,	1.2425,
+	0.899e-6,	1.2303,
+	0.763e-6,	4.3633,
+	0.236e-6,	4.3590,
+	0.163e-6,	0.2705,
+	0.541e-6,	0.2710,
+	1.157e-6,	0.2590,
+	0.099e-6,	0.1798,
+	0.360e-6,	2.4237,
+	0.234e-6,	2.3740,
+	0.253e-6,	4.5365,
+	0.849e-6,	4.5293,
+	2.954e-6,	4.5364,
+	0.282e-6,	4.4581,
+	1.550e-6,	1.3570,
+	0.472e-6,	1.3561,
+	0.135e-6,	1.3579,
+	0.081e-6,	3.5936,
+	0.087e-6,	3.5500,
+	0.087e-6,	5.7334,
+	0,
+
+	0.181e-6,	5.8275,
+	0.095e-6,	2.2427,
+	0.319e-6,	2.2534,
+	0.256e-6,	2.2403,
+	0.157e-6,	4.8292,
+	0.106e-6,	1.0332,
+	0.397e-6,	1.0756,
+	0.143e-6,	4.0980,
+	0,
+
+	0.222e-6,	1.6024,
+	0.708e-6,	1.5949,
+	0.191e-6,	5.7914,
+	0.100e-6,	5.3564,
+	0.347e-6,	5.3548,
+	1.185e-6,	5.3576,
+	3.268e-6,	5.3579,
+	0.371e-6,	2.2148,
+	0.160e-6,	2.1241,
+	0.134e-6,	5.1260,
+	0.347e-6,	5.1620,
+	0,
+};
+
+char	merccp[] =
+{
+	 4,	1,
+	 3,	1,
+	 2,	1,
+	 1,	1,
+	 0,	1,
+	-1,	1,
+	-2,	1,
+	 6,	2,
+	 5,	2,
+	 4,	2,
+	 3,	2,
+	 2,	2,
+	 1,	2,
+	 0,	2,
+	-1,	2,
+	-2,	2,
+	-3,	2,
+	 5,	3,
+	 4,	3,
+	 3,	3,
+	 2,	3,
+	 1,	3,
+	 0,	3,
+	-1,	3,
+	 5,	4,
+	 4,	4,
+	 3,	4,
+	 2,	4,
+	 1,	4,
+	 0,	4,
+	 7,	5,
+	 6,	5,
+	 5,	5,
+	 4,	5,
+	 3,	5,
+	 2,	5,
+	 1,	5,
+	 0,	5,
+	-1,	5,
+	-2,	5,
+	 4,	6,
+	 3,	6,
+	 5,	7,
+	 4,	7,
+	 3,	7,
+	 2,	7,
+	 5,	8,
+	 4,	8,
+	 3,	8,
+	 2,	8,
+	 5,	9,
+	 4,	9,
+	 5,	10,
+	 4,	10,
+	 3,	10,
+
+	 3,	1,
+	 2,	1,
+	 1,	1,
+	 0,	1,
+	-1,	1,
+	 4,	2,
+	 3,	2,
+	 2,	2,
+	 1,	2,
+	 0,	2,
+	-1,	2,
+	 3,	3,
+	 2,	3,
+	 1,	3,
+	 0,	3,
+	 4,	4,
+	 3,	4,
+	 2,	4,
+	 1,	4,
+	 0,	4,
+	-1,	4,
+	 2,	5,
+
+	 4,	1,
+	 3,	1,
+	 2,	1,
+	 1,	1,
+	 0,	1,
+	-1,	1,
+	-2,	1,
+	-3,	1,
+	 5,	2,
+	 4,	2,
+	 3,	2,
+	 2,	2,
+	 1,	2,
+	 0,	2,
+	-1,	2,
+	-2,	2,
+	 3,	3,
+	 2,	3,
+	 1,	3,
+	 0,	3,
+	-1,	3,
+	 1,	4,
+
+	 1,	1,
+	 0,	1,
+	-1,	1,
+	 3,	2,
+	 2,	2,
+	 1,	2,
+	 0,	2,
+	-1,	2,
+	 2,	3,
+	 1,	3,
+
+	 2,	1,
+	 1,	1,
+	 0,	1,
+	-1,	1,
+	 4,	2,
+	 3,	2,
+	 2,	2,
+	 1,	2,
+	 0,	2,
+	-1,	2,
+	 4,	3,
+	 3,	3,
+	 2,	3,
+	 0,	3,
+	 3,	4,
+	 2,	4,
+	 5,	5,
+	 4,	5,
+	 3,	5,
+	 2,	5,
+	 1,	5,
+	 0,	5,
+	-1,	5,
+	 4,	6,
+	 3,	6,
+	 4,	7,
+
+	 1,	1,
+	 3,	2,
+	 2,	2,
+	 1,	2,
+	 2,	3,
+	 3,	4,
+	 2,	4,
+	 0,	4,
+
+	 2,	1,
+	 1,	1,
+	-1,	1,
+	 4,	2,
+	 3,	2,
+	 2,	2,
+	 1,	2,
+	 0,	2,
+	-1,	2,
+	 2,	3,
+	 1,	3,
+};
blob - /dev/null
blob + 8ad239a77189d68ce79e6e137518d328c1ff0c76 (mode 644)
--- /dev/null
+++ src/cmd/astro/mkfile
@@ -0,0 +1,39 @@
+<$PLAN9/src/mkhdr
+
+TARG=astro
+OFILES=\
+	moon.$O\
+	moont.$O\
+	satel.$O\
+	merct.$O\
+	search.$O\
+	dist.$O\
+	sunt.$O\
+	occ.$O\
+	main.$O\
+	sat.$O\
+	venus.$O\
+	pdate.$O\
+	sun.$O\
+	init.$O\
+	star.$O\
+	merc.$O\
+	stars.$O\
+	comet.$O\
+	nutate.$O\
+	helio.$O\
+	mars.$O\
+	output.$O\
+	jup.$O\
+	geo.$O\
+	venust.$O\
+	cosadd.$O\
+	nutt.$O\
+	uran.$O\
+	nept.$O\
+	plut.$O\
+
+HFILES=astro.h\
+
+SHORTLIB=bio 9
+<$PLAN9/src/mkone
blob - /dev/null
blob + 0467ff2b000fc90a1a5d6f2956f78b6efeeaefef (mode 644)
--- /dev/null
+++ src/cmd/astro/moon.c
@@ -0,0 +1,379 @@
+#include "astro.h"
+
+double k1, k2, k3, k4;
+double mnom, msun, noded, dmoon;
+
+void
+moon(void)
+{
+	Moontab *mp;
+	double dlong, lsun, psun;
+	double eccm, eccs, chp, cpe;
+	double v0, t0, m0, j0;
+	double arg1, arg2, arg3, arg4, arg5, arg6, arg7;
+	double arg8, arg9, arg10;
+	double dgamma, k5, k6;
+	double lterms, sterms, cterms, nterms, pterms, spterms;
+	double gamma1, gamma2, gamma3, arglat;
+	double xmp, ymp, zmp;
+	double obl2;
+
+/*
+ *	the fundamental elements - all referred to the epoch of
+ *	Jan 0.5, 1900 and to the mean equinox of date.
+ */
+
+	dlong = 270.434164 + 13.1763965268*eday - .001133*capt2
+		 + 2.e-6*capt3;
+	argp = 334.329556 + .1114040803*eday - .010325*capt2
+		 - 12.e-6*capt3;
+	node = 259.183275 - .0529539222*eday + .002078*capt2
+		 + 2.e-6*capt3;
+	lsun = 279.696678 + .9856473354*eday + .000303*capt2;
+	psun = 281.220833 + .0000470684*eday + .000453*capt2
+		 + 3.e-6*capt3;
+
+	dlong = fmod(dlong, 360.);
+	argp = fmod(argp, 360.);
+	node = fmod(node, 360.);
+	lsun = fmod(lsun, 360.);
+	psun = fmod(psun, 360.);
+
+	eccm = 22639.550;
+	eccs = .01675104 - .00004180*capt;
+	incl = 18461.400;
+	cpe = 124.986;
+	chp = 3422.451;
+
+/*
+ *	some subsidiary elements - they are all longitudes
+ *	and they are referred to the epoch 1/0.5 1900 and
+ *	to the fixed mean equinox of 1850.0.
+ */
+
+	v0 = 342.069128 + 1.6021304820*eday;
+	t0 =  98.998753 + 0.9856091138*eday;
+	m0 = 293.049675 + 0.5240329445*eday;
+	j0 = 237.352319 + 0.0830912295*eday;
+
+/*
+ *	the following are periodic corrections to the
+ *	fundamental elements and constants.
+ *	arg3 is the "Great Venus Inequality".
+ */
+
+	arg1 = 41.1 + 20.2*(capt+.5);
+	arg2 = dlong - argp + 33. + 3.*t0 - 10.*v0 - 2.6*(capt+.5);
+	arg3 = dlong - argp + 151.1 + 16.*t0 - 18.*v0 - (capt+.5);
+	arg4 = node;
+	arg5 = node + 276.2 - 2.3*(capt+.5);
+	arg6 = 313.9 + 13.*t0 - 8.*v0;
+	arg7 = dlong - argp + 112.0 + 29.*t0 - 26.*v0;
+	arg8 = dlong + argp - 2.*lsun + 273. + 21.*t0 - 20.*v0;
+	arg9 = node + 290.1 - 0.9*(capt+.5);
+	arg10 = 115. + 38.5*(capt+.5);
+	arg1 *= radian;
+	arg2 *= radian;
+	arg3 *= radian;
+	arg4 *= radian;
+	arg5 *= radian;
+	arg6 *= radian;
+	arg7 *= radian;
+	arg8 *= radian;
+	arg9 *= radian;
+	arg10 *= radian;
+
+	dlong +=
+		   (0.84 *sin(arg1)
+		 +  0.31 *sin(arg2)
+		 + 14.27 *sin(arg3)
+		 +  7.261*sin(arg4)
+		 +  0.282*sin(arg5)
+		 +  0.237*sin(arg6)
+		 +  0.108*sin(arg7)
+		 +  0.126*sin(arg8))/3600.;
+
+	argp +=
+		 (- 2.10 *sin(arg1)
+		 -  0.118*sin(arg3)
+		 -  2.076*sin(arg4)
+		 -  0.840*sin(arg5)
+		 -  0.593*sin(arg6))/3600.;
+
+	node +=
+		   (0.63*sin(arg1)
+		 +  0.17*sin(arg3)
+		 + 95.96*sin(arg4)
+		 + 15.58*sin(arg5)
+		 +  1.86*sin(arg9))/3600.;
+
+	t0 +=
+		 (- 6.40*sin(arg1)
+		 -  1.89*sin(arg6))/3600.;
+
+	psun +=
+		   (6.40*sin(arg1)
+		 +  1.89*sin(arg6))/3600.;
+
+	dgamma = -  4.318*cos(arg4)
+		 -  0.698*cos(arg5)
+		 -  0.083*cos(arg9);
+
+	j0 +=
+		   0.33*sin(arg10);
+
+/*
+ *	the following factors account for the fact that the
+ *	eccentricity, solar eccentricity, inclination and
+ *	parallax used by Brown to make up his coefficients
+ *	are both wrong and out of date.  Brown did the same
+ *	thing in a different way.
+ */
+
+	k1 = eccm/22639.500;
+	k2 = eccs/.01675104;
+	k3 = 1. + 2.708e-6 + .000108008*dgamma;
+	k4 = cpe/125.154;
+	k5 = chp/3422.700;
+
+/*
+ *	the principal arguments that are used to compute
+ *	perturbations are the following differences of the
+ *	fundamental elements.
+ */
+
+	mnom = dlong - argp;
+	msun = lsun - psun;
+	noded = dlong - node;
+	dmoon = dlong - lsun;
+
+/*
+ *	solar terms in longitude
+ */
+
+	lterms = 0.0;
+	mp = moontab;
+	for(;;) {
+		if(mp->f == 0.0)
+			break;
+		lterms += sinx(mp->f,
+			mp->c[0], mp->c[1],
+			mp->c[2], mp->c[3], 0.0);
+		mp++;
+	}
+	mp++;
+
+/*
+ *	planetary terms in longitude
+ */
+
+	lterms += sinx(0.822, 0,0,0,0, t0-v0);
+	lterms += sinx(0.307, 0,0,0,0, 2.*t0-2.*v0+179.8);
+	lterms += sinx(0.348, 0,0,0,0, 3.*t0-2.*v0+272.9);
+	lterms += sinx(0.176, 0,0,0,0, 4.*t0-3.*v0+271.7);
+	lterms += sinx(0.092, 0,0,0,0, 5.*t0-3.*v0+199.);
+	lterms += sinx(0.129, 1,0,0,0, -t0+v0+180.);
+	lterms += sinx(0.152, 1,0,0,0, t0-v0);
+	lterms += sinx(0.127, 1,0,0,0, 3.*t0-3.*v0+180.);
+	lterms += sinx(0.099, 0,0,0,2, t0-v0);
+	lterms += sinx(0.136, 0,0,0,2, 2.*t0-2.*v0+179.5);
+	lterms += sinx(0.083, -1,0,0,2, -4.*t0+4.*v0+180.);
+	lterms += sinx(0.662, -1,0,0,2, -3.*t0+3.*v0+180.0);
+	lterms += sinx(0.137, -1,0,0,2, -2.*t0+2.*v0);
+	lterms += sinx(0.133, -1,0,0,2, t0-v0);
+	lterms += sinx(0.157, -1,0,0,2, 2.*t0-2.*v0+179.6);
+	lterms += sinx(0.079, -1,0,0,2, -8.*t0+6.*v0+162.6);
+	lterms += sinx(0.073, 2,0,0,-2, 3.*t0-3.*v0+180.);
+	lterms += sinx(0.643, 0,0,0,0, -t0+j0+178.8);
+	lterms += sinx(0.187, 0,0,0,0, -2.*t0+2.*j0+359.6);
+	lterms += sinx(0.087, 0,0,0,0, j0+289.9);
+	lterms += sinx(0.165, 0,0,0,0, -t0+2.*j0+241.5);
+	lterms += sinx(0.144, 1,0,0,0, t0-j0+1.0);
+	lterms += sinx(0.158, 1,0,0,0, -t0+j0+179.0);
+	lterms += sinx(0.190, 1,0,0,0, -2.*t0+2.*j0+180.0);
+	lterms += sinx(0.096, 1,0,0,0, -2.*t0+3.*j0+352.5);
+	lterms += sinx(0.070, 0,0,0,2, 2.*t0-2.*j0+180.);
+	lterms += sinx(0.167, 0,0,0,2, -t0+j0+178.5);
+	lterms += sinx(0.085, 0,0,0,2, -2.*t0+2.*j0+359.2);
+	lterms += sinx(1.137, -1,0,0,2, 2.*t0-2.*j0+180.3);
+	lterms += sinx(0.211, -1,0,0,2, -t0+j0+178.4);
+	lterms += sinx(0.089, -1,0,0,2, -2.*t0+2.*j0+359.2);
+	lterms += sinx(0.436, -1,0,0,2, 2.*t0-3.*j0+7.5);
+	lterms += sinx(0.240, 2,0,0,-2, -2.*t0+2.*j0+179.9);
+	lterms += sinx(0.284, 2,0,0,-2, -2.*t0+3.*j0+172.5);
+	lterms += sinx(0.195, 0,0,0,0, -2.*t0+2.*m0+180.2);
+	lterms += sinx(0.327, 0,0,0,0, -t0+2.*m0+224.4);
+	lterms += sinx(0.093, 0,0,0,0, -2.*t0+4.*m0+244.8);
+	lterms += sinx(0.073, 1,0,0,0, -t0+2.*m0+223.3);
+	lterms += sinx(0.074, 1,0,0,0, t0-2.*m0+306.3);
+	lterms += sinx(0.189, 0,0,0,0, node+180.);
+
+/*
+ *	solar terms in latitude
+ */
+
+	sterms = 0;
+	for(;;) {
+		if(mp->f == 0)
+			break;
+		sterms += sinx(mp->f,
+			mp->c[0], mp->c[1],
+			mp->c[2], mp->c[3], 0);
+		mp++;
+	}
+	mp++;
+
+	cterms = 0;
+	for(;;) {
+		if(mp->f == 0)
+			break;
+		cterms += cosx(mp->f,
+			mp->c[0], mp->c[1],
+			mp->c[2], mp->c[3], 0);
+		mp++;
+	}
+	mp++;
+
+	nterms = 0;
+	for(;;) {
+		if(mp->f == 0)
+			break;
+		nterms += sinx(mp->f,
+			mp->c[0], mp->c[1],
+			mp->c[2], mp->c[3], 0);
+		mp++;
+	}
+	mp++;
+
+/*
+ *	planetary terms in latitude
+ */
+
+	pterms =
+		   sinx(0.215, 0,0,0,0, dlong);
+
+/*
+ *	solar terms in parallax
+ */
+
+	spterms = 3422.700;
+	for(;;) {
+		if(mp->f == 0)
+			break;
+		spterms += cosx(mp->f,
+			mp->c[0], mp->c[1],
+			mp->c[2], mp->c[3], 0);
+		mp++;
+	}
+
+/*
+ *	planetary terms in parallax
+ */
+
+	spterms = spterms;
+
+/*
+ *	computation of longitude
+ */
+
+	lambda = (dlong + lterms/3600.)*radian;
+
+/*
+ *	computation of latitude
+ */
+
+	arglat = (noded + sterms/3600.)*radian;
+	gamma1 = 18519.700 * k3;
+	gamma2 = -6.241 * k3*k3*k3;
+	gamma3 = 0.004 * k3*k3*k3*k3*k3;
+
+	k6 = (gamma1 + cterms) / gamma1;
+
+	beta = k6 * (gamma1*sin(arglat) + gamma2*sin(3.*arglat)
+		 + gamma3*sin(5.*arglat) + nterms)
+		 + pterms;
+	if(flags['o'])
+		beta -= 0.6;
+	beta *= radsec;
+
+/*
+ *	computation of parallax
+ */
+
+	spterms = k5 * spterms *radsec;
+	hp = spterms + (spterms*spterms*spterms)/6.;
+
+	rad = hp/radsec;
+	rp = 1.;
+	semi = .0799 + .272453*(hp/radsec);
+	if(dmoon < 0.)
+		dmoon += 360.;
+	mag = dmoon/360.;
+
+/*
+ *	change to equatorial coordinates
+ */
+
+	lambda += phi;
+	obl2 = obliq + eps;
+	xmp = rp*cos(lambda)*cos(beta);
+	ymp = rp*(sin(lambda)*cos(beta)*cos(obl2) - sin(obl2)*sin(beta));
+	zmp = rp*(sin(lambda)*cos(beta)*sin(obl2) + cos(obl2)*sin(beta));
+
+	alpha = atan2(ymp, xmp);
+	delta = atan2(zmp, sqrt(xmp*xmp+ymp*ymp));
+	meday = eday;
+	mhp = hp;
+
+	geo();
+}
+
+double
+sinx(double coef, int i, int j, int k, int m, double angle)
+{
+	double x;
+
+	x = i*mnom + j*msun + k*noded + m*dmoon + angle;
+	x = coef*sin(x*radian);
+	if(i < 0)
+		i = -i;
+	for(; i>0; i--)
+		x *= k1;
+	if(j < 0)
+		j = -j;
+	for(; j>0; j--)
+		x *= k2;
+	if(k < 0)
+		k = -k;
+	for(; k>0; k--)
+		x *= k3;
+	if(m & 1)
+		x *= k4;
+
+	return x;
+}
+
+double
+cosx(double coef, int i, int j, int k, int m, double angle)
+{
+	double x;
+
+	x = i*mnom + j*msun + k*noded + m*dmoon + angle;
+	x = coef*cos(x*radian);
+	if(i < 0)
+		i = -i;
+	for(; i>0; i--)
+		x *= k1;
+	if(j < 0)
+		j = -j;
+	for(; j>0; j--)
+		x *= k2;
+	if(k < 0)
+		k = -k;
+	for(; k>0; k--)
+		x *= k3;
+	if(m & 1)
+		x *= k4;
+
+	return x;
+}
blob - /dev/null
blob + 1509492e8cf0aa0fe37ebb82f2bcb23fbb67ae0b (mode 644)
--- /dev/null
+++ src/cmd/astro/moont.c
@@ -0,0 +1,290 @@
+#include "astro.h"
+
+Moontab	moontab[] =
+{
+	    0.127,	0,0,0,6,
+	   13.902,	0,0,0,4,
+	 2369.912,	0,0,0,2,
+	    1.979,	1,0,0,4,
+	  191.953,	1,0,0,2,
+	22639.500,	1,0,0,0,
+	-4586.465,	1,0,0,-2,
+	  -38.428,	1,0,0,-4,
+	    -.393,	1,0,0,-6,
+	    -.289,	0,1,0,4,
+	  -24.420,	0,1,0,2,
+	 -668.146,	0,1,0,0,
+	 -165.145,	0,1,0,-2,
+	   -1.877,	0,1,0,-4,
+	    0.403,	0,0,0,3,
+	 -125.154,	0,0,0,1,
+	    0.213,	2,0,0,4,
+	   14.387,	2,0,0,2,
+	  769.016,	2,0,0,0,
+	 -211.656,	2,0,0,-2,
+	  -30.773,	2,0,0,-4,
+	    -.570,	2,0,0,-6,
+	   -2.921,	1,1,0,2,
+	 -109.673,	1,1,0,0,
+	 -205.962,	1,1,0,-2,
+	   -4.391,	1,1,0,-4,
+	    -.072,	1,1,0,-6,
+	    0.283,	1,-1,0,4,
+	   14.577,	1,-1,0,2,
+	  147.687,	1,-1,0,0,
+	   28.475,	1,-1,0,-2,
+	    0.636,	1,-1,0,-4,
+	    -.189,	0,2,0,2,
+	   -7.486,	0,2,0,0,
+	   -8.096,	0,2,0,-2,
+	    -.151,	0,2,0,-4,
+	    -.085,	0,0,2,4,
+	   -5.741,	0,0,2,2,
+	 -411.608,	0,0,2,0,
+	  -55.173,	0,0,2,-2,
+	   -8.466,	1,0,0,1,
+	   18.609,	1,0,0,-1,
+	    3.215,	1,0,0,-3,
+	    0.150,	0,1,0,3,
+	   18.023,	0,1,0,1,
+	    0.560,	0,1,0,-1,
+	    1.060,	3,0,0,2,
+	   36.124,	3,0,0,0,
+	  -13.193,	3,0,0,-2,
+	   -1.187,	3,0,0,-4,
+	    -.293,	3,0,0,-6,
+	    -.290,	2,1,0,2,
+	   -7.649,	2,1,0,0,
+	   -8.627,	2,1,0,-2,
+	   -2.740,	2,1,0,-4,
+	    -.091,	2,1,0,-6,
+	    1.181,	2,-1,0,2,
+	    9.703,	2,-1,0,0,
+	   -2.494,	2,-1,0,-2,
+	    0.360,	2,-1,0,-4,
+	   -1.167,	1,2,0,0,
+	   -7.412,	1,2,0,-2,
+	    -.311,	1,2,0,-4,
+	    0.757,	1,-2,0,2,
+	    2.580,	1,-2,0,0,
+	    2.533,	1,-2,0,-2,
+	    -.103,	0,3,0,0,
+	    -.344,	0,3,0,-2,
+	    -.992,	1,0,2,2,
+	  -45.099,	1,0,2,0,
+	    -.179,	1,0,2,-2,
+	    -.301,	1,0,2,-4,
+	   -6.382,	1,0,-2,2,
+	   39.528,	1,0,-2,0,
+	    9.366,	1,0,-2,-2,
+	    0.202,	1,0,-2,-4,
+	    0.415,	0,1,2,0,
+	   -2.152,	0,1,2,-2,
+	   -1.440,	0,1,-2,2,
+	    0.076,	0,1,-2,0,
+	    0.384,	0,1,-2,-2,
+	    -.586,	2,0,0,1,
+	    1.750,	2,0,0,-1,
+	    1.225,	2,0,0,-3,
+	    1.267,	1,1,0,1,
+	    0.137,	1,1,0,-1,
+	    0.233,	1,1,0,-3,
+	    -.122,	1,-1,0,1,
+	   -1.089,	1,-1,0,-1,
+	    -.276,	1,-1,0,-3,
+	    0.255,	0,0,2,1,
+	    0.584,	0,0,2,-1,
+	    0.254,	0,0,2,-3,
+	    0.070,	4,0,0,2,
+	    1.938,	4,0,0,0,
+	    -.952,	4,0,0,-2,
+	    -.551,	3,1,0,0,
+	    -.482,	3,1,0,-2,
+	    -.100,	3,1,0,-4,
+	    0.088,	3,-1,0,2,
+	    0.681,	3,-1,0,0,
+	    -.183,	3,-1,0,-2,
+	    -.297,	2,2,0,-2,
+	    -.161,	2,2,0,-4,
+	    0.197,	2,-2,0,0,
+	    0.254,	2,-2,0,-2,
+	    -.250,	1,3,0,-2,
+	    -.123,	2,0,2,2,
+	   -3.996,	2,0,2,0,
+	    0.557,	2,0,2,-2,
+	    -.459,	2,0,-2,2,
+	   -1.370,	2,0,-2,0,
+	    0.538,	2,0,-2,-2,
+	    0.173,	2,0,-2,-4,
+	    0.263,	1,1,2,0,
+	    0.083,	1,1,-2,2,
+	    -.083,	1,1,-2,0,
+	    0.426,	1,1,-2,-2,
+	    -.304,	1,-1,2,0,
+	    -.372,	1,-1,-2,2,
+	    0.083,	1,-1,-2,0,
+	    0.418,	0,0,4,0,
+	    0.074,	0,0,4,-2,
+	    0.130,	3,0,0,-1,
+	    0.092,	2,1,0,1,
+	    0.084,	2,1,0,-3,
+	    -.352,	2,-1,0,-1,
+	    0.113,	5,0,0,0,
+	    -.330,	3,0,2,0,
+	    0.090,	1,0,4,0,
+	    -.080,	1,0,-4,0,
+	        0,	0,0,0,0,
+
+	 -112.79,	0,0,0,1,
+	 2373.36,	0,0,0,2,
+	   -4.01,	0,0,0,3,
+	   14.06,	0,0,0,4,
+	    6.98,	1,0,0,4,
+	  192.72,	1,0,0,2,
+	  -13.51,	1,0,0,1,
+	22609.07,	1,0,0,0,
+	    3.59,	1,0,0,-1,
+	-4578.13,	1,0,0,-2,
+	    5.44,	1,0,0,-3,
+	  -38.64,	1,0,0,-4,
+	   14.78,	2,0,0,2,
+	  767.96,	2,0,0,0,
+	    2.01,	2,0,0,-1,
+	 -152.53,	2,0,0,-2,
+	  -34.07,	2,0,0,-4,
+	    2.96,	3,0,0,2,
+	   50.64,	3,0,0,0,
+	  -16.40,	3,0,0,-2,
+	    3.60,	4,0,0,0,
+	   -1.58,	4,0,0,-2,
+	   -1.59,	0,1,0,4,
+	  -25.10,	0,1,0,2,
+	   17.93,	0,1,0,1,
+	 -126.98,	0,1,0,0,
+	 -165.06,	0,1,0,-2,
+	   -6.46,	0,1,0,-4,
+	   -1.68,	0,2,0,2,
+	  -16.35,	0,2,0,-2,
+	  -11.75,	1,1,0,2,
+	    1.52,	1,1,0,1,
+	 -115.18,	1,1,0,0,
+	 -182.36,	1,1,0,-2,
+	   -9.66,	1,1,0,-4,
+	   -2.27,	-1,1,0,4,
+	  -23.59,	-1,1,0,2,
+	 -138.76,	-1,1,0,0,
+	  -31.70,	-1,1,0,-2,
+	   -1.53,	-1,1,0,-4,
+	  -10.56,	2,1,0,0,
+	   -7.59,	2,1,0,-2,
+	   -2.54,	2,1,0,-4,
+	    3.32,	2,-1,0,2,
+	   11.67,	2,-1,0,0,
+	   -6.12,	1,2,0,-2,
+	   -2.40,	-1,2,0,2,
+	   -2.32,	-1,2,0,0,
+	   -1.82,	-1,2,0,-2,
+	  -52.14,	0,0,2,-2,
+	   -1.67,	0,0,2,-4,
+	   -9.52,	1,0,2,-2,
+	  -85.13,	-1,0,2,0,
+	    3.37,	-1,0,2,-2,
+	   -2.26,	0,1,2,-2,
+	       0,	0,0,0,0,
+
+	   -0.725,	0,0,0,1,
+	    0.601,	0,0,0,2,
+	    0.394,	0,0,0,3,
+	    -.445,	1,0,0,4,
+	    0.455,	1,0,0,1,
+	    0.192,	1,0,0,-3,
+	    5.679,	2,0,0,-2,
+	    -.308,	2,0,0,-4,
+	    -.166,	3,0,0,2,
+	   -1.300,	3,0,0,0,
+	    0.258,	3,0,0,-2,
+	   -1.302,	0,1,0,0,
+	    -.416,	0,1,0,-4,
+	    -.740,	0,2,0,-2,
+	    0.787,	1,1,0,2,
+	    0.461,	1,1,0,0,
+	    2.056,	1,1,0,-2,
+	    -.471,	1,1,0,-4,
+	    -.443,	-1,1,0,2,
+	    0.679,	-1,1,0,0,
+	   -1.540,	-1,1,0,-2,
+	    0.259,	2,1,0,0,
+	    -.212,	2,-1,0,2,
+	    -.151,	2,-1,0,0,
+	        0,	0,0,0,0,
+
+	 -526.069,	0,0,1,-2,
+	   -3.352,	0,0,1,-4,
+	   44.297,	1,0,1,-2,
+	   -6.000,	1,0,1,-4,
+	   20.599,	-1,0,1,0,
+	  -30.598,	-1,0,1,-2,
+	  -24.649,	-2,0,1,0,
+	   -2.000,	-2,0,1,-2,
+	  -22.571,	0,1,1,-2,
+	   10.985,	0,-1,1,-2,
+	        0,	0,0,0,0,
+
+	    0.2607,	0,0,0,4,
+	   28.2333,	0,0,0,2,
+	    0.0433,	1,0,0,4,
+	    3.0861,	1,0,0,2,
+	  186.5398,	1,0,0,0,
+	   34.3117,	1,0,0,-2,
+	    0.6008,	1,0,0,-4,
+	    -.3000,	0,1,0,2,
+	    -.3997,	0,1,0,0,
+	    1.9178,	0,1,0,-2,
+	    0.0339,	0,1,0,-4,
+	   -0.9781,	0,0,0,1,
+	    0.2833,	2,0,0,2,
+	   10.1657,	2,0,0,0,
+	    -.3039,	2,0,0,-2,
+	    0.3722,	2,0,0,-4,
+	    0.0109,	2,0,0,-6,
+	    -.0484,	1,1,0,2,
+	    -.9490,	1,1,0,0,
+	    1.4437,	1,1,0,-2,
+	    0.0673,	1,1,0,-4,
+	    0.2302,	1,-1,0,2,
+	    1.1528,	1,-1,0,0,
+	    -.2257,	1,-1,0,-2,
+	    -.0102,	1,-1,0,-4,
+	    0.0918,	0,2,0,-2,
+	    -.0124,	0,0,2,0,
+	    -.1052,	0,0,2,-2,
+	    -.1093,	1,0,0,1,
+	    0.0118,	1,0,0,-1,
+	    -.0386,	1,0,0,-3,
+	    0.1494,	0,1,0,1,
+	    0.0243,	3,0,0,2,
+	    0.6215,	3,0,0,0,
+	    -.1187,	3,0,0,-2,
+	    -.1038,	2,1,0,0,
+	    -.0192,	2,1,0,-2,
+	    0.0324,	2,1,0,-4,
+	    0.0213,	2,-1,0,2,
+	    0.1268,	2,-1,0,0,
+	    -.0106,	1,2,0,0,
+	    0.0484,	1,2,0,-2,
+	    0.0112,	1,-2,0,2,
+	    0.0196,	1,-2,0,0,
+	    -.0212,	1,-2,0,-2,
+	    -.0833,	1,0,2,-2,
+	    -.0481,	1,0,-2,2,
+	    -.7136,	1,0,-2,0,
+	    -.0112,	1,0,-2,-2,
+	    -.0100,	2,0,0,1,
+	    0.0155,	2,0,0,-1,
+	    0.0164,	1,1,0,1,
+	    0.0401,	4,0,0,0,
+	    -.0130,	4,0,0,-2,
+	    0.0115,	3,-1,0,0,
+	    -.0141,	2,0,-2,-2,
+	         0,	0,0,0,0,
+};
blob - /dev/null
blob + 2d05d59c649b0b6380d828db68153c0a5465c2d8 (mode 644)
--- /dev/null
+++ src/cmd/astro/nept.c
@@ -0,0 +1,154 @@
+#include "astro.h"
+
+static	double	elem[] =
+{
+	36525.0,		// [0] eday of epoc
+
+	30.06896348,		// [1] semi major axis (au)
+	0.00858587,		// [2] eccentricity
+ 	1.76917,		// [3] inclination (deg)
+	131.72169,		// [4] longitude of the ascending node (deg)
+	44.97135,		// [5] longitude of perihelion (deg)
+	304.88003,		// [6] mean longitude (deg)
+
+	-0.00125196,		// [1+6] (au/julian century)
+	0.0000251,		// [2+6] (e/julian century)
+  	-3.64,			// [3+6] (arcsec/julian century)
+	-151.25,		// [4+6] (arcsec/julian century)
+	-844.43,		// [5+6] (arcsec/julian century)
+	786449.21,		// [6+6] (arcsec/julian century)
+};
+
+void
+nept(void)
+{
+	double pturbl, pturbb, pturbr;
+	double lograd;
+	double dele, enom, vnom, nd, sl;
+
+	double capj, capn, eye, comg, omg;
+	double sb, su, cu, u, b, up;
+	double sd, ca, sa;
+
+	double cy;
+
+	cy = (eday - elem[0]) / 36525.;		// per julian century
+
+	mrad = elem[1] + elem[1+6]*cy;
+	ecc = elem[2] + elem[2+6]*cy;
+
+	cy = cy / 3600;				// arcsec/deg per julian century
+	incl = elem[3] + elem[3+6]*cy;
+	node = elem[4] + elem[4+6]*cy;
+	argp = elem[5] + elem[5+6]*cy;
+
+	anom = elem[6] + elem[6+6]*cy - argp;
+	motion = elem[6+6] / 36525. / 3600;
+
+	incl *= radian;
+	node *= radian;
+	argp *= radian;
+	anom = fmod(anom,360.)*radian;
+
+	enom = anom + ecc*sin(anom);
+	do {
+		dele = (anom - enom + ecc * sin(enom)) /
+			(1. - ecc*cos(enom));
+		enom += dele;
+	} while(fabs(dele) > converge);
+	vnom = 2.*atan2(sqrt((1.+ecc)/(1.-ecc))*sin(enom/2.),
+		cos(enom/2.));
+	rad = mrad*(1. - ecc*cos(enom));
+
+	lambda = vnom + argp;
+	pturbl = 0.;
+	lambda += pturbl*radsec;
+	pturbb = 0.;
+	pturbr = 0.;
+
+/*
+ *	reduce to the ecliptic
+ */
+
+	nd = lambda - node;
+	lambda = node + atan2(sin(nd)*cos(incl),cos(nd));
+
+	sl = sin(incl)*sin(nd) + pturbb*radsec;
+	beta = atan2(sl, pyth(sl));
+
+	lograd = pturbr*2.30258509;
+	rad *= 1. + lograd;
+
+
+	lambda -= 1185.*radsec;
+	beta -= 51.*radsec;
+
+	motion *= radian*mrad*mrad/(rad*rad);
+	semi = 83.33;
+
+/*
+ *	here begins the computation of magnitude
+ *	first find the geocentric equatorial coordinates of Saturn
+ */
+
+	sd = rad*(cos(beta)*sin(lambda)*sin(obliq) +
+		sin(beta)*cos(obliq));
+	sa = rad*(cos(beta)*sin(lambda)*cos(obliq) -
+		sin(beta)*sin(obliq));
+	ca = rad*cos(beta)*cos(lambda);
+	sd += zms;
+	sa += yms;
+	ca += xms;
+	alpha = atan2(sa,ca);
+	delta = atan2(sd,sqrt(sa*sa+ca*ca));
+
+/*
+ *	here are the necessary elements of Saturn's rings
+ *	cf. Exp. Supp. p. 363ff.
+ */
+
+	capj = 6.9056 - 0.4322*capt;
+	capn = 126.3615 + 3.9894*capt + 0.2403*capt2;
+	eye = 28.0743 - 0.0128*capt;
+	comg = 168.1179 + 1.3936*capt;
+	omg = 42.9236 - 2.7390*capt - 0.2344*capt2;
+
+	capj *= radian;
+	capn *= radian;
+	eye *= radian;
+	comg *= radian;
+	omg *= radian;
+
+/*
+ *	now find saturnicentric ring-plane coords of the earth
+ */
+
+	sb = sin(capj)*cos(delta)*sin(alpha-capn) -
+		cos(capj)*sin(delta);
+	su = cos(capj)*cos(delta)*sin(alpha-capn) +
+		sin(capj)*sin(delta);
+	cu = cos(delta)*cos(alpha-capn);
+	u = atan2(su,cu);
+	b = atan2(sb,sqrt(su*su+cu*cu));
+
+/*
+ *	and then the saturnicentric ring-plane coords of the sun
+ */
+
+	su = sin(eye)*sin(beta) +
+		cos(eye)*cos(beta)*sin(lambda-comg);
+	cu = cos(beta)*cos(lambda-comg);
+	up = atan2(su,cu);
+
+/*
+ *	at last, the magnitude
+ */
+
+
+	sb = sin(b);
+	mag = -8.68 +2.52*fabs(up+omg-u)-
+		2.60*fabs(sb) + 1.25*(sb*sb);
+
+	helio();
+	geo();
+}
blob - /dev/null
blob + bc7daa31ab02b26a839ad05018ff16c8fdc088c4 (mode 644)
--- /dev/null
+++ src/cmd/astro/nutate.c
@@ -0,0 +1,86 @@
+#include "astro.h"
+
+void
+nutate(void)
+{
+
+/*
+ *	uses radian, radsec
+ *	sets phi, eps, dphi, deps, obliq, gst, tobliq
+ */
+
+	double msun, mnom, noded, dmoon;
+
+/*
+ *	nutation of the equinoxes is a wobble of the pole
+ *	of the earths rotation whose magnitude is about
+ *	9 seconds of arc and whose period is about 18.6 years.
+ *
+ *	it depends upon the pull of the sun and moon on the
+ *	equatorial bulge of the earth.
+ *
+ *	phi and eps are the two angles which specify the
+ *	true pole with respect to the mean pole.
+ *
+ *	all coeffieients are from Exp. Supp. pp.44-45
+ */
+
+	mnom = 296.104608 + 13.0649924465*eday + 9.192e-3*capt2
+		 + 14.38e-6*capt3;
+	mnom *= radian;
+	msun = 358.475833 + .9856002669*eday - .150e-3*capt2
+		 - 3.33e-6*capt3;
+	msun *= radian;
+	noded = 11.250889 + 13.2293504490*eday - 3.211e-3*capt2
+		 - 0.33e-6*capt3;
+	noded *= radian;
+	dmoon = 350.737486 + 12.1907491914*eday - 1.436e-3*capt2
+		 + 1.89e-6*capt3;
+	dmoon *= radian;
+	node = 259.183275 - .0529539222*eday + 2.078e-3*capt2
+		 + 2.22e-6*capt3;
+	node *= radian;
+
+/*
+ *	long period terms
+ */
+
+	phi = 0.;
+	eps = 0.;
+	dphi = 0.;
+	deps = 0.;
+
+
+	icosadd(nutfp, nutcp);
+	phi = -(17.2327+.01737*capt)*sin(node);
+	phi += sinadd(4, node, noded, dmoon, msun);
+
+	eps = cosadd(4, node, noded, dmoon, msun);
+
+/*
+ *	short period terms
+ */
+
+
+	dphi = sinadd(4, node, noded, mnom, dmoon);
+
+	deps = cosadd(3, node, noded, mnom);
+
+	phi = (phi+dphi)*radsec;
+	eps = (eps+deps)*radsec;
+	dphi *= radsec;
+	deps *= radsec;
+
+	obliq = 23.452294 - .0130125*capt - 1.64e-6*capt2
+		 + 0.503e-6*capt3;
+	obliq *= radian;
+	tobliq = obliq + eps;
+
+	gst = 99.690983 + 360.9856473354*eday + .000387*capt2;
+	gst -= 180.;
+	gst = fmod(gst, 360.);
+	if(gst < 0.)
+		gst += 360.;
+	gst *= radian;
+	gst += phi*cos(obliq);
+}
blob - /dev/null
blob + 8ddf2b91314d03818554190855e3239e9f8edd96 (mode 644)
--- /dev/null
+++ src/cmd/astro/nutt.c
@@ -0,0 +1,71 @@
+#include "astro.h"
+
+double	nutfp[] =
+{
+	  .2088,	0,
+	-1.2730,	0,
+	  .1258,	0,
+	 -.0496,	0,
+	  .0214,	0,
+	  .0124,	0,
+	      0,
+
+	 9.2109,	0,
+	 -.0904,	0,
+	  .5519,	0,
+	  .0215,	0,
+	 -.0093,	0,
+	 -.0066,	0,
+	      0,
+
+	 -.2037,	0,
+	  .0675,	0,
+	 -.0342,	0,
+	 -.0261,	0,
+	 -.0149,	0,
+	  .0114,	0,
+	  .0060,	0,
+	  .0058,	0,
+	 -.0057,	0,
+	 -.0052,	0,
+	      0,
+
+	  .0884,	0,
+	  .0183,	0,
+	  .0113,	0,
+	 -.0050,	0,
+	      0,
+};
+
+char	nutcp[] =
+{
+	2,0,0,0,
+	2,2,-2,0,
+	0,0,0,1,
+	2,2,-2,1,
+	2,2,-2,-1,
+	1,2,-2,0,
+
+	1,0,0,0,
+	2,0,0,0,
+	2,2,-2,0,
+	2,2,-2,1,
+	2,2,-2,-1,
+	1,2,-2,0,
+
+	2,2,0,0,
+	0,0,1,0,
+	1,2,0,0,
+	2,2,1,0,
+	0,0,1,-2,
+	2,2,-1,0,
+	0,0,0,2,
+	1,0,1,0,
+	1,0,-1,0,
+	2,2,-1,2,
+
+	2,2,0,
+	1,2,0,
+	2,2,1,
+	2,2,-1,
+};
blob - /dev/null
blob + 0b9802cfea01b5ad4dfca0168b99524ac5e4b489 (mode 644)
--- /dev/null
+++ src/cmd/astro/occ.c
@@ -0,0 +1,192 @@
+#include "astro.h"
+
+Occ	 o1, o2;
+Obj2	 xo1, xo2;
+
+void
+occult(Obj2 *p1, Obj2 *p2, double d)
+{
+	int i, i1, N;
+	double d1, d2, d3, d4;
+	double x, di, dx, x1;
+
+	USED(d);
+
+	d3 = 0;
+	d2 = 0;
+	occ.t1 = -100;
+	occ.t2 = -100;
+	occ.t3 = -100;
+	occ.t4 = -100;
+	occ.t5 = -100;
+	for(i=0; i<=NPTS+1; i++) {
+		d1 = d2;
+		d2 = d3;
+		d3 = dist(&p1->point[i], &p2->point[i]);
+		if(i >= 2 && d2 <= d1 && d2 <= d3)
+			goto found;
+	}
+	return;
+
+found:
+	N = 2880*PER/NPTS; /* 1 min steps */
+	i -= 2;
+	set3pt(p1, i, &o1);
+	set3pt(p2, i, &o2);
+
+	di = i;
+	x = 0;
+	dx = 2./N;
+	for(i=0; i<=N; i++) {
+		setpt(&o1, x);
+		setpt(&o2, x);
+		d1 = d2;
+		d2 = d3;
+		d3 = dist(&o1.act, &o2.act);
+		if(i >= 2 && d2 <= d1 && d2 <= d3)
+			goto found1;
+		x += dx;
+	}
+	fprint(2, "bad 1 \n");
+	return;
+
+found1:
+	if(d2 > o1.act.semi2+o2.act.semi2+50)
+		return;
+	di += x - 3*dx;
+	x = 0;
+	for(i=0; i<3; i++) {
+		setime(day + deld*(di + x));
+		(*p1->obj)();
+		setobj(&xo1.point[i]);
+		(*p2->obj)();
+		setobj(&xo2.point[i]);
+		x += 2*dx;
+	}
+	dx /= 60;
+	x = 0;
+	set3pt(&xo1, 0, &o1);
+	set3pt(&xo2, 0, &o2);
+	for(i=0; i<=240; i++) {
+		setpt(&o1, x);
+		setpt(&o2, x);
+		d1 = d2;
+		d2 = d3;
+		d3 = dist(&o1.act, &o2.act);
+		if(i >= 2 && d2 <= d1 && d2 <= d3)
+			goto found2;
+		x += 1./120.;
+	}
+	fprint(2, "bad 2 \n");
+	return;
+
+found2:
+	if(d2 > o1.act.semi2 + o2.act.semi2)
+		return;
+	i1 = i-1;
+	x1 = x - 1./120.;
+	occ.t3 = di + i1 * dx;
+	occ.e3 = o1.act.el;
+	d3 = o1.act.semi2 - o2.act.semi2;
+	if(d3 < 0)
+		d3 = -d3;
+	d4 = o1.act.semi2 + o2.act.semi2;
+	for(i=i1,x=x1;; i++) {
+		setpt(&o1, x);
+		setpt(&o2, x);
+		d1 = d2;
+		d2 = dist(&o1.act, &o2.act);
+		if(i != i1) {
+			if(d1 <= d3 && d2 > d3) {
+				occ.t4 = di + (i-.5) * dx;
+				occ.e4 = o1.act.el;
+			}
+			if(d2 > d4) {
+				if(d1 <= d4) {
+					occ.t5 = di + (i-.5) * dx;
+					occ.e5 = o1.act.el;
+				}
+				break;
+			}
+		}
+		x += 1./120.;
+	}
+	for(i=i1,x=x1;; i--) {
+		setpt(&o1, x);
+		setpt(&o2, x);
+		d1 = d2;
+		d2 = dist(&o1.act, &o2.act);
+		if(i != i1) {
+			if(d1 <= d3 && d2 > d3) {
+				occ.t2 = di + (i+.5) * dx;
+				occ.e2 = o1.act.el;
+			}
+			if(d2 > d4) {
+				if(d1 <= d4) {
+					occ.t1 = di + (i+.5) * dx;
+					occ.e1 = o1.act.el;
+				}
+				break;
+			}
+		}
+		x -= 1./120.;
+	}
+}
+
+void
+setpt(Occ *o, double x)
+{
+	double y;
+
+	y = x * (x-1);
+	o->act.ra = o->del0.ra +
+		x*o->del1.ra + y*o->del2.ra;
+	o->act.decl2 = o->del0.decl2 +
+		x*o->del1.decl2 + y*o->del2.decl2;
+	o->act.semi2 = o->del0.semi2 +
+		x*o->del1.semi2 + y*o->del2.semi2;
+	o->act.el = o->del0.el +
+		x*o->del1.el + y*o->del2.el;
+}
+
+
+double
+pinorm(double a)
+{
+
+	while(a < -pi)
+		a += pipi;
+	while(a > pi)
+		a -= pipi;
+	return a;
+}
+
+void
+set3pt(Obj2 *p, int i, Occ *o)
+{
+	Obj1 *p1, *p2, *p3;
+	double a;
+
+	p1 = p->point+i;
+	p2 = p1+1;
+	p3 = p2+1;
+
+	o->del0.ra = p1->ra;
+	o->del0.decl2 = p1->decl2;
+	o->del0.semi2 = p1->semi2;
+	o->del0.el = p1->el;
+
+	a = p2->ra - p1->ra;
+	o->del1.ra = pinorm(a);
+	a = p2->decl2 - p1->decl2;
+	o->del1.decl2 = pinorm(a);
+	o->del1.semi2 = p2->semi2 - p1->semi2;
+	o->del1.el = p2->el - p1->el;
+
+	a = p1->ra + p3->ra - 2*p2->ra;
+	o->del2.ra = pinorm(a)/2;
+	a = p1->decl2 + p3->decl2 - 2*p2->decl2;
+	o->del2.decl2 = pinorm(a)/2;
+	o->del2.semi2 = (p1->semi2 + p3->semi2 - 2*p2->semi2) / 2;
+	o->del2.el = (p1->el + p3->el - 2*p2->el) / 2;
+}
blob - /dev/null
blob + 7c4c27979154d0e48a5e8bcba8729878b61db7f9 (mode 644)
--- /dev/null
+++ src/cmd/astro/output.c
@@ -0,0 +1,53 @@
+#include "astro.h"
+
+void
+output(char *s, Obj1 *p)
+{
+
+	if(s == 0)
+		print(" SAO %5ld", sao);
+	else
+		print("%10s", s);
+	print(" %R %D %9.4f %9.4f %9.4f",
+		p->ra, p->decl2, p->az, p->el, p->semi2);
+	if(s == osun.name || s == omoon.name)
+		print(" %7.4f", p->mag);
+	print("\n");
+}
+
+int
+Rconv(Fmt *f)
+{
+	double v;
+	int h, m, c;
+
+	v = va_arg(f->args, double);
+	v = fmod(v*12/pi, 24);		/* now hours */
+	h = floor(v);
+	v = fmod((v-h)*60, 60);		/* now leftover minutes */
+	m = floor(v);
+	v = fmod((v-m)*60, 60);		/* now leftover seconds */
+	c = floor(v);
+	return fmtprint(f, "%2dh%.2dm%.2ds", h, m, c);
+}
+
+int
+Dconv(Fmt *f1)
+{
+	double v;
+	int h, m, c, f;
+
+	v = va_arg(f1->args, double);
+	v = fmod(v/radian, 360);	/* now degrees */
+	f = 0;
+	if(v > 180) {
+		v = 360 - v;
+		f = 1;
+	}
+	h = floor(v);
+	v = fmod((v-h)*60, 60);		/* now leftover minutes */
+	m = floor(v);
+	v = fmod((v-m)*60, 60);		/* now leftover seconds */
+	c = floor(v);
+	return fmtprint(f1, "%c%.2d°%.2d'%.2d\"", "+-"[f], h, m, c);
+}
blob - /dev/null
blob + e88d7006acc447a67a5a0b7af58401b26b3ee378 (mode 644)
--- /dev/null
+++ src/cmd/astro/pdate.c
@@ -0,0 +1,313 @@
+#include "astro.h"
+
+
+char*	month[] =
+{
+	"January",
+	"February",
+	"March",
+	"April",
+	"May",
+	"June",
+	"July",
+	"August",
+	"September",
+	"October",
+	"November",
+	"December",
+};
+
+double
+dsrc(double d, Tim *t, int i)
+{
+	double y;
+
+	do {
+		t->ifa[i] += 1.;
+		y = convdate(t);
+	} while(d >= y);
+	do {
+		t->ifa[i] -= 1.;
+		y = convdate(t);
+	} while(d < y);
+	return d - y;
+}
+
+void
+dtsetup(double d, Tim *t)
+{
+	double v;
+
+	t->ifa[0] = floor(1900 + d/365.24220);
+	t->ifa[1] = 1;
+	t->ifa[2] = 1;
+	t->ifa[3] = 0;
+	t->ifa[4] = 0;
+	t->ifa[1] = floor(1 + dsrc(d, t, 0)/30);
+	t->ifa[2] = floor(1 + dsrc(d, t, 1));
+	dsrc(d, t, 2);
+
+	v = (d - convdate(t)) * 24;
+	t->ifa[3] = floor(v);
+	t->ifa[4] = (v - t->ifa[3]) * 60;
+	convdate(t);	/* to set timezone */
+}
+
+void
+pdate(double d)
+{
+	int i;
+	Tim t;
+
+	dtsetup(d, &t);
+	if(flags['s']) {
+		i = t.ifa[1];
+		print("%s ", month[i-1]);
+		i = t.ifa[2];
+		numb(i);
+		print("...");
+		return;
+	}
+
+	/* year month day */
+	print("%4d %2d %2d",
+		(int)t.ifa[0],
+		(int)t.ifa[1],
+		(int)t.ifa[2]);
+}
+
+void
+ptime(double d)
+{
+	int h, m, s;
+	char *mer;
+	Tim t;
+
+	if(flags['s']) {
+		/* hour minute */
+		dtsetup(d + .5/(24*60), &t);
+		h = t.ifa[3];
+		m = floor(t.ifa[4]);
+
+		mer = "AM";
+		if(h >= 12) {
+			mer = "PM";
+			h -= 12;
+		}
+		if(h == 0)
+			h = 12;
+		numb(h);
+		if(m < 10) {
+			if(m == 0) {
+				print("%s exactly ...", mer);
+				return;
+			}
+			print("O ");
+		}
+		numb(m);
+		print("%s ...", mer);
+		return;
+	}
+	/* hour minute second */
+	dtsetup(d, &t);
+	h = t.ifa[3];
+	m = floor(t.ifa[4]);
+	s = floor((t.ifa[4]-m) * 60);
+	print("%.2d:%.2d:%.2d %.*s", h, m, s, utfnlen(t.tz, 3), t.tz);
+}
+
+char*	unit[] =
+{
+	"zero",
+	"one",
+	"two",
+	"three",
+	"four",
+	"five",
+	"six",
+	"seven",
+	"eight",
+	"nine",
+	"ten",
+	"eleven",
+	"twelve",
+	"thirteen",
+	"fourteen",
+	"fifteen",
+	"sixteen",
+	"seventeen",
+	"eighteen",
+	"nineteen"
+};
+char*	decade[] =
+{
+	"twenty",
+	"thirty",
+	"forty",
+	"fifty",
+	"sixty",
+	"seventy",
+	"eighty",
+	"ninety"
+};
+
+void
+pstime(double d)
+{
+
+	setime(d);
+
+	semi = 0;
+	motion = 0;
+	rad = 1.e9;
+	lambda = 0;
+	beta = 0;
+
+// uses lambda, beta, rad, motion
+// sets alpha, delta, rp
+
+	helio();
+
+// uses alpha, delta, rp
+// sets ra, decl, lha, decl2, az, el
+
+	geo();
+
+	print(" %R %D %D %4.0f", lha, nlat, awlong, elev/3.28084);
+}
+
+void
+numb(int n)
+{
+
+	if(n >= 100) {
+		print("%d ", n);
+		return;
+	}
+	if(n >= 20) {
+		print("%s ", decade[n/10 - 2]);
+		n %= 10;
+		if(n == 0)
+			return;
+	}
+	print("%s ", unit[n]);
+}
+
+double
+tzone(double y, Tim *z)
+{
+	double t, l1, l2;
+	Tm t1, t2;
+
+	/*
+	 * get a rough approximation to unix mean time
+	 */
+	t = (y - 25567.5) * 86400;
+
+	/*
+	 * if outside unix conversions,
+	 * just call it GMT
+	 */
+	if(t < 0 || t > 2.1e9)
+		return y;
+
+	/*
+	 * convert by both local and gmt
+	 */
+	t1 = *localtime((long)t);
+	t2 = *gmtime((long)t);
+
+	/*
+	 * pick up year crossings
+	 */
+	if(t1.yday == 0 && t2.yday > 1)
+		t1.yday = t2.yday+1;
+	if(t2.yday == 0 && t1.yday > 1)
+		t2.yday = t1.yday+1;
+
+	/*
+	 * convert times to days
+	 */
+	l1 = t1.yday + t1.hour/24. + t1.min/1440. + t1.sec/86400.;
+	l2 = t2.yday + t2.hour/24. + t2.min/1440. + t2.sec/86400.;
+
+	/*
+	 * return difference
+	 */
+	strncpy(z->tz, t1.zone, sizeof(z->tz));
+	return y + (l2 - l1);
+}
+
+int	dmo[12] =
+{
+	0,
+	31,
+	59,
+	90,
+	120,
+	151,
+	181,
+	212,
+	243,
+	273,
+	304,
+	334
+};
+
+/*
+ * input date conversion
+ * output is done by zero crossing
+ * on this input conversion.
+ */
+double
+convdate(Tim *t)
+{
+	double y, d;
+	int m;
+
+	y = t->ifa[0];
+	m = t->ifa[1];
+	d = t->ifa[2];
+
+	/*
+	 * normalize the month
+	 */
+	while(m < 1) {
+		m += 12;
+		y -= 1;
+	}
+	while(m > 12) {
+		m -= 12;
+		y += 1;
+	}
+
+	/*
+	 * bc correction
+	 */
+	if(y < 0)
+		y += 1;
+
+	/*
+	 * normal conversion
+	 */
+	y += 4712;
+	if(fmod(y, 4) == 0 && m > 2)
+		d += 1;
+	y = y*365 + floor((y+3)/4) + dmo[m-1] + d - 1;
+
+	/*
+	 * gregorian change
+	 */
+	if(y > 2361232)
+		y -= floor((y-1794167)/36524.220) -
+			floor((y-1721117)/146100);
+	y += t->ifa[3]/24 + t->ifa[4]/1440 - 2415020.5;
+
+	/*
+	 * kitchen clock correction
+	 */
+	strncpy(t->tz, "GMT", sizeof(t->tz));
+	if(flags['k'])
+		y = tzone(y, t);
+	return y;
+}
blob - /dev/null
blob + 36702a80eb80e2f86b67a54aae537972010e5f13 (mode 644)
--- /dev/null
+++ src/cmd/astro/plut.c
@@ -0,0 +1,154 @@
+#include "astro.h"
+
+static	double	elem[] =
+{
+	36525.0,		// [0] eday of epoc
+
+	39.48168677,		// [1] semi major axis (au)
+	0.24880766,		// [2] eccentricity
+ 	17.14175,		// [3] inclination (deg)
+	110.30347,		// [4] longitude of the ascending node (deg)
+	224.06676,		// [5] longitude of perihelion (deg)
+	238.92881,		// [6] mean longitude (deg)
+
+	-0.00076912,		// [1+6] (au/julian century)
+	0.00006465,		// [2+6] (e/julian century)
+  	11.07,			// [3+6] (arcsec/julian century)
+	-37.33,			// [4+6] (arcsec/julian century)
+	-132.25,		// [5+6] (arcsec/julian century)
+	522747.90,		// [6+6] (arcsec/julian century)
+};
+
+void
+plut(void)
+{
+	double pturbl, pturbb, pturbr;
+	double lograd;
+	double dele, enom, vnom, nd, sl;
+
+	double capj, capn, eye, comg, omg;
+	double sb, su, cu, u, b, up;
+	double sd, ca, sa;
+
+	double cy;
+
+	cy = (eday - elem[0]) / 36525.;		// per julian century
+
+	mrad = elem[1] + elem[1+6]*cy;
+	ecc = elem[2] + elem[2+6]*cy;
+
+	cy = cy / 3600;				// arcsec/deg per julian century
+	incl = elem[3] + elem[3+6]*cy;
+	node = elem[4] + elem[4+6]*cy;
+	argp = elem[5] + elem[5+6]*cy;
+
+	anom = elem[6] + elem[6+6]*cy - argp;
+	motion = elem[6+6] / 36525. / 3600;
+
+	incl *= radian;
+	node *= radian;
+	argp *= radian;
+	anom = fmod(anom,360.)*radian;
+
+	enom = anom + ecc*sin(anom);
+	do {
+		dele = (anom - enom + ecc * sin(enom)) /
+			(1. - ecc*cos(enom));
+		enom += dele;
+	} while(fabs(dele) > converge);
+	vnom = 2.*atan2(sqrt((1.+ecc)/(1.-ecc))*sin(enom/2.),
+		cos(enom/2.));
+	rad = mrad*(1. - ecc*cos(enom));
+
+	lambda = vnom + argp;
+	pturbl = 0.;
+	lambda += pturbl*radsec;
+	pturbb = 0.;
+	pturbr = 0.;
+
+/*
+ *	reduce to the ecliptic
+ */
+
+	nd = lambda - node;
+	lambda = node + atan2(sin(nd)*cos(incl),cos(nd));
+
+	sl = sin(incl)*sin(nd) + pturbb*radsec;
+	beta = atan2(sl, pyth(sl));
+
+	lograd = pturbr*2.30258509;
+	rad *= 1. + lograd;
+
+
+	lambda -= 1185.*radsec;
+	beta -= 51.*radsec;
+
+	motion *= radian*mrad*mrad/(rad*rad);
+	semi = 83.33;
+
+/*
+ *	here begins the computation of magnitude
+ *	first find the geocentric equatorial coordinates of Saturn
+ */
+
+	sd = rad*(cos(beta)*sin(lambda)*sin(obliq) +
+		sin(beta)*cos(obliq));
+	sa = rad*(cos(beta)*sin(lambda)*cos(obliq) -
+		sin(beta)*sin(obliq));
+	ca = rad*cos(beta)*cos(lambda);
+	sd += zms;
+	sa += yms;
+	ca += xms;
+	alpha = atan2(sa,ca);
+	delta = atan2(sd,sqrt(sa*sa+ca*ca));
+
+/*
+ *	here are the necessary elements of Saturn's rings
+ *	cf. Exp. Supp. p. 363ff.
+ */
+
+	capj = 6.9056 - 0.4322*capt;
+	capn = 126.3615 + 3.9894*capt + 0.2403*capt2;
+	eye = 28.0743 - 0.0128*capt;
+	comg = 168.1179 + 1.3936*capt;
+	omg = 42.9236 - 2.7390*capt - 0.2344*capt2;
+
+	capj *= radian;
+	capn *= radian;
+	eye *= radian;
+	comg *= radian;
+	omg *= radian;
+
+/*
+ *	now find saturnicentric ring-plane coords of the earth
+ */
+
+	sb = sin(capj)*cos(delta)*sin(alpha-capn) -
+		cos(capj)*sin(delta);
+	su = cos(capj)*cos(delta)*sin(alpha-capn) +
+		sin(capj)*sin(delta);
+	cu = cos(delta)*cos(alpha-capn);
+	u = atan2(su,cu);
+	b = atan2(sb,sqrt(su*su+cu*cu));
+
+/*
+ *	and then the saturnicentric ring-plane coords of the sun
+ */
+
+	su = sin(eye)*sin(beta) +
+		cos(eye)*cos(beta)*sin(lambda-comg);
+	cu = cos(beta)*cos(lambda-comg);
+	up = atan2(su,cu);
+
+/*
+ *	at last, the magnitude
+ */
+
+
+	sb = sin(b);
+	mag = -8.68 +2.52*fabs(up+omg-u)-
+		2.60*fabs(sb) + 1.25*(sb*sb);
+
+	helio();
+	geo();
+}
blob - /dev/null
blob + 02aa2e6fee71ad5c5d59bb206cc280aa8467b46d (mode 644)
--- /dev/null
+++ src/cmd/astro/sat.c
@@ -0,0 +1,128 @@
+#include "astro.h"
+
+void
+sat(void)
+{
+	double pturbl, pturbb, pturbr;
+	double lograd;
+	double dele, enom, vnom, nd, sl;
+
+	double capj, capn, eye, comg, omg;
+	double sb, su, cu, u, b, up;
+	double sd, ca, sa;
+
+	ecc = .0558900 - .000347*capt;
+	incl = 2.49256 - .0044*capt;
+	node = 112.78364 + .87306*capt;
+	argp = 91.08897 + 1.95917*capt;
+	mrad = 9.538843;
+	anom = 175.47630 + .03345972*eday - .56527*capt;
+	motion = 120.4550/3600.;
+
+	incl *= radian;
+	node *= radian;
+	argp *= radian;
+	anom = fmod(anom, 360.)*radian;
+
+	enom = anom + ecc*sin(anom);
+	do {
+		dele = (anom - enom + ecc * sin(enom)) /
+			(1. - ecc*cos(enom));
+		enom += dele;
+	} while(fabs(dele) > converge);
+	vnom = 2.*atan2(sqrt((1.+ecc)/(1.-ecc))*sin(enom/2.),
+		cos(enom/2.));
+	rad = mrad*(1. - ecc*cos(enom));
+
+	lambda = vnom + argp;
+	pturbl = 0.;
+	lambda += pturbl*radsec;
+	pturbb = 0.;
+	pturbr = 0.;
+
+/*
+ *	reduce to the ecliptic
+ */
+
+	nd = lambda - node;
+	lambda = node + atan2(sin(nd)*cos(incl),cos(nd));
+
+	sl = sin(incl)*sin(nd) + pturbb*radsec;
+	beta = atan2(sl, pyth(sl));
+
+	lograd = pturbr*2.30258509;
+	rad *= 1. + lograd;
+
+
+	lambda -= 1185.*radsec;
+	beta -= 51.*radsec;
+
+	motion *= radian*mrad*mrad/(rad*rad);
+	semi = 83.33;
+
+/*
+ *	here begins the computation of magnitude
+ *	first find the geocentric equatorial coordinates of Saturn
+ */
+
+	sd = rad*(cos(beta)*sin(lambda)*sin(obliq) +
+		sin(beta)*cos(obliq));
+	sa = rad*(cos(beta)*sin(lambda)*cos(obliq) -
+		sin(beta)*sin(obliq));
+	ca = rad*cos(beta)*cos(lambda);
+	sd += zms;
+	sa += yms;
+	ca += xms;
+	alpha = atan2(sa,ca);
+	delta = atan2(sd,sqrt(sa*sa+ca*ca));
+
+/*
+ *	here are the necessary elements of Saturn's rings
+ *	cf. Exp. Supp. p. 363ff.
+ */
+
+	capj = 6.9056 - 0.4322*capt;
+	capn = 126.3615 + 3.9894*capt + 0.2403*capt2;
+	eye = 28.0743 - 0.0128*capt;
+	comg = 168.1179 + 1.3936*capt;
+	omg = 42.9236 - 2.7390*capt - 0.2344*capt2;
+
+	capj *= radian;
+	capn *= radian;
+	eye *= radian;
+	comg *= radian;
+	omg *= radian;
+
+/*
+ *	now find saturnicentric ring-plane coords of the earth
+ */
+
+	sb = sin(capj)*cos(delta)*sin(alpha-capn) -
+		cos(capj)*sin(delta);
+	su = cos(capj)*cos(delta)*sin(alpha-capn) +
+		sin(capj)*sin(delta);
+	cu = cos(delta)*cos(alpha-capn);
+	u = atan2(su,cu);
+	b = atan2(sb,sqrt(su*su+cu*cu));
+
+/*
+ *	and then the saturnicentric ring-plane coords of the sun
+ */
+
+	su = sin(eye)*sin(beta) +
+		cos(eye)*cos(beta)*sin(lambda-comg);
+	cu = cos(beta)*cos(lambda-comg);
+	up = atan2(su,cu);
+
+/*
+ *	at last, the magnitude
+ */
+
+
+	sb = sin(b);
+	mag = -8.68 +2.52*fabs(up+omg-u)-
+		2.60*fabs(sb) + 1.25*(sb*sb);
+
+	helio();
+	geo();
+}
blob - /dev/null
blob + 38206e5f9649ded5cf86e2168b314284217e693a (mode 644)
--- /dev/null
+++ src/cmd/astro/satel.c
@@ -0,0 +1,201 @@
+#include "astro.h"
+
+char*	satlst[] =
+{
+	0,
+};
+
+struct
+{
+	double	time;
+	double	tilt;
+	double	pnni;
+	double	psi;
+	double	ppi;
+	double	d1pp;
+	double	peri;
+	double	d1per;
+	double	e0;
+	double	deo;
+	double	rdp;
+	double	st;
+	double	ct;
+	double	rot;
+	double	semi;
+} satl;
+
+void
+satels(void)
+{
+	double ifa[10], t, t1, t2, tinc;
+	char **satp;
+	int flag, f, i, n;
+
+	satp = satlst;
+
+loop:
+	if(*satp == 0)
+		return;
+	f = open(*satp, 0);
+	if(f < 0) {
+		fprint(2, "cannot open %s\n", *satp);
+		satp += 2;
+		goto loop;
+	}
+	satp++;
+	rline(f);
+	tinc = atof(skip(6));
+	rline(f);
+	rline(f);
+	for(i=0; i<9; i++)
+		ifa[i] = atof(skip(i));
+	n = ifa[0];
+	i = ifa[1];
+	t = dmo[i-1] + ifa[2] - 1.;
+	if(n%4 == 0 && i > 2)
+		t += 1.;
+	for(i=1970; i<n; i++) {
+		t += 365.;
+		if(i%4 == 0)
+			t += 1.;
+	}
+	t = (t * 24. + ifa[3]) * 60. + ifa[4];
+	satl.time = t * 60.;
+	satl.tilt = ifa[5] * radian;
+	satl.pnni = ifa[6] * radian;
+	satl.psi = ifa[7];
+	satl.ppi = ifa[8] * radian;
+	rline(f);
+	for(i=0; i<5; i++)
+		ifa[i] = atof(skip(i));
+	satl.d1pp = ifa[0] * radian;
+	satl.peri = ifa[1];
+	satl.d1per = ifa[2];
+	satl.e0 = ifa[3];
+	satl.deo = 0;
+	satl.rdp = ifa[4];
+
+	satl.st = sin(satl.tilt);
+	satl.ct = cos(satl.tilt);
+	satl.rot = pipi / (1440. + satl.psi);
+	satl.semi = satl.rdp * (1. + satl.e0);
+
+	n = PER*288.; /* 5 min steps */
+	t = day;
+	for(i=0; i<n; i++) {
+		if(sunel((t-day)/deld) > 0.)
+			goto out;
+		satel(t);
+		if(el > 0) {
+			t1 = t;
+			flag = 0;
+			do {
+				if(el > 30.)
+					flag++;
+				t -= tinc/(24.*3600.);
+				satel(t);
+			} while(el > 0.);
+			t2 = (t - day)/deld;
+			t = t1;
+			do {
+				t += tinc/(24.*3600.);
+				satel(t);
+				if(el > 30.)
+					flag++;
+			} while(el > 0.);
+			if(flag)
+				if((*satp)[0] == '-')
+					event("%s pass at ", (*satp)+1, "",
+						t2, SIGNIF+PTIME+DARK); else
+					event("%s pass at ", *satp, "",
+						t2, PTIME+DARK);
+		}
+	out:
+		t += 5./(24.*60.);
+	}
+	close(f);
+	satp++;
+	goto loop;
+}
+
+void
+satel(double time)
+{
+	int i;
+	double amean, an, coc, csl, d, de, enom, eo;
+	double pp, q, rdp, slong, ssl, t, tp;
+
+	i = 500;
+	el = -1;
+	time = (time-25567.5) * 86400;
+	t = (time - satl.time)/60;
+	if(t < 0)
+		return; /* too early for satelites */
+	an = floor(t/satl.peri);
+	while(an*satl.peri + an*an*satl.d1per/2. <= t) {
+		an += 1;
+		if(--i == 0)
+			return;
+	}
+	while((tp = an*satl.peri + an*an*satl.d1per/2.) > t) {
+		an -= 1;
+		if(--i == 0)
+			return;
+	}
+	amean = (t-tp)/(satl.peri+(an+.5)*satl.d1per);
+	pp = satl.ppi+(an+amean)*satl.d1pp;
+	amean *= pipi;
+	eo = satl.e0+satl.deo*an;
+	rdp = satl.semi/(1+eo);
+	enom = amean+eo*sin(amean);
+	do {
+		de = (amean-enom+eo*sin(enom))/(1.0-eo*cos(enom));
+		enom += de;
+		if(--i == 0)
+			return;
+	} while(fabs(de) >= 1.0e-6);
+	q = 3963.35*erad/(rdp*(1-eo*cos(enom))/(1-eo));
+	d = pp + 2*atan2(sqrt((1+eo)/(1-eo))*sin(enom/2),cos(enom/2));
+	slong = satl.pnni + t*satl.rot -
+		atan2(satl.ct*sin(d), cos(d));
+	ssl = satl.st*sin(d);
+	csl = pyth(ssl);
+	if(vis(time, atan2(ssl,csl), slong, q)) {
+		coc = ssl*sin(glat) + csl*cos(glat)*cos(wlong-slong);
+		el = atan2(coc-q, pyth(coc));
+		el /= radian;
+	}
+}
+
+int
+vis(double t, double slat, double slong, double q)
+{
+	double t0, t1, t2, d;
+
+	d = t/86400 - .005375 + 3653;
+	t0 = 6.238030674 + .01720196977*d;
+	t2 = t0 + .0167253303*sin(t0);
+	do {
+		t1 = (t0 - t2 + .0167259152*sin(t2)) /
+			(1 - .0167259152*cos(t2));
+		t2 = t2 + t1;
+	} while(fabs(t1) >= 1.e-4);
+	t0 = 2*atan2(1.01686816*sin(t2/2), cos(t2/2));
+	t0 = 4.926234925 + 8.214985538e-7*d + t0;
+	t1 = 0.91744599 * sin(t0);
+	t0 = atan2(t1, cos(t0));
+	if(t0 < -pi/2)
+		t0 = t0 + pipi;
+	d = 4.88097876 + 6.30038809*d - t0;
+	t0 = 0.43366079 * t1;
+	t1 = pyth(t0);
+	t2 = t1*cos(slat)*cos(d-slong) - t0*sin(slat);
+	if(t2 > 0.46949322e-2) {
+		if(0.46949322e-2*t2 + 0.999988979*pyth(t2) < q)
+			return 0;
+	}
+	t2 = t1*cos(glat)*cos(d-wlong) - t0*sin(glat);
+	if(t2 < .1)
+		return 0;
+	return 1;
+}
blob - /dev/null
blob + e4ed4eda8d8550fc04044a477746df4891869a8d (mode 644)
--- /dev/null
+++ src/cmd/astro/search.c
@@ -0,0 +1,155 @@
+#include "astro.h"
+
+char*	solstr[] =
+{
+	"Fall equinox",
+	"Winter solstice",
+	"Spring equinox",
+	"Summer solstice",
+};
+
+struct
+{
+	double	beta;
+	int	rta;
+	int	dec;
+	char	*betstr;
+} bettab[] =
+{
+	-1.3572, 231,	50,	"Quadrantid",
+	 0.7620, 336,	0,	"Eta aquarid",
+	 1.5497, 260,	-20,	"Ophiuchid",
+	 2.1324, 315,	-15,	"Capricornid",
+	 2.1991, 339,	-17,	"Delta aquarid",
+	 2.2158, 340,	-30,	"Pisces australid",
+	 2.4331, 46,	58,	"Perseid",
+	-2.6578, 95,	15,	"Orionid",
+	-1.8678, 15,	-55,	"Phoenicid",
+	-1.7260, 113,	32,	"Geminid",
+	0
+};
+
+void
+search(void)
+{
+	Obj2 *p, *q;
+	int i, j;
+	double t;
+
+	for(i=0; objlst[i]; i++) {
+		p = objlst[i];
+		if(p == &oshad)
+			continue;
+		t = rise(p, -.833);
+		if(t >= 0.)
+			event("%s rises at ", p->name, "", t,
+				i==0? PTIME: PTIME|DARK);
+		t = set(p, -.833);
+		if(t >= 0.)
+			event("%s sets at ", p->name, "", t,
+				i==0? PTIME: PTIME|DARK);
+		if(p == &osun) {
+			for(j=0; j<4; j++) {
+				t = solstice(j);
+				if(t >= 0)
+					event("%s at ", solstr[j], "", t,
+						SIGNIF|PTIME);
+			}
+			for(j=0; bettab[j].beta!=0; j++) {
+				t = betcross(bettab[j].beta);
+				if(t >= 0)
+					event("%s  meeteeor shouwer",
+					bettab[j].betstr, "", t, SIGNIF);
+			}
+			t = rise(p, -18);
+			if(t >= 0)
+				event("Twilight starts at ", "", "", t, PTIME);
+			t = set(p, -18);
+			if(t >= 0)
+				event("Twilight ends at ", "", "", t, PTIME);
+		}
+		if(p == &omoon)
+		for(j=0; j<NPTS; j++) {
+			if(p->point[j].mag > .75 && p->point[j+1].mag < .25)
+				event("New moon", "", "", 0, 0);
+			if(p->point[j].mag <= .25 && p->point[j+1].mag > .25)
+				event("First quarter moon", "", "", 0, 0);
+			if(p->point[j].mag <= .50 && p->point[j+1].mag > .50)
+				event("Full moon", "", "", 0, 0);
+			if(p->point[j].mag <= .75 && p->point[j+1].mag > .75)
+				event("Last quarter moon", "", "", 0, 0);
+		}
+		if(p == &omerc || p == &ovenus) {
+			t = melong(p);
+			if(t >= 0) {
+				t = rise(p, 0) - rise(&osun, 0);
+				if(t < 0)
+					t += NPTS;
+				if(t > NPTS)
+					t -= NPTS;
+				if(t > NPTS/2)
+				event("Morning elongation of %s", p->name,
+					"", 0, SIGNIF);
+				else
+				event("Evening elongation of %s", p->name,
+					"", 0, SIGNIF);
+			}
+		}
+		for(j=i; objlst[j]; j++) {
+			if(i == j)
+				continue;
+			q = objlst[j];
+			if(p == &omoon || q == &omoon) {
+				occult(p, q, 0);
+				if(occ.t3 < 0)
+					continue;
+				if(p == &osun || q == &oshad) {
+					if(occ.t1 >= 0)
+					event("Partial eclipse of %s begins at ", p->name, "",
+						occ.t1, SIGNIF|PTIME);
+					if(occ.t2 >= 0)
+					event("Total eclipse of %s begins at ", p->name, "",
+						occ.t2, SIGNIF|PTIME);
+					if(occ.t4 >= 0)
+					event("Total eclipse of %s ends at ", p->name, "",
+						occ.t4, SIGNIF|PTIME);
+					if(occ.t5 >= 0)
+					event("Partial eclipse of %s ends at ", p->name, "",
+						occ.t5, SIGNIF|PTIME);
+				} else {
+					if(occ.t1 >= 0)
+					event("Occultation of %s begins at ", q->name, "",
+						occ.t1, SIGNIF|PTIME);
+					if(occ.t5 >= 0)
+					event("Occultation of %s ends at ", q->name, "",
+						occ.t5, SIGNIF|PTIME);
+				}
+				continue;
+			}
+			if(p == &osun) {
+				if(q != &omerc && q != &ovenus)
+					continue;
+				occult(p, q, -1);
+				if(occ.t3 >= 0.) {
+					if(occ.t1 >= 0)
+					event("Transit of %s begins at ", q->name, "",
+						occ.t1, SIGNIF|LIGHT|PTIME);
+					if(occ.t5 >= 0)
+					event("Transit of %s ends at ", q->name, "",
+						occ.t5, SIGNIF|LIGHT|PTIME);
+				}
+				continue;
+			}
+			t = dist(&p->point[0], &q->point[0]);
+			if(t > 5000)
+				continue;
+			event("%s is in the house of %s",
+				p->name, q->name, 0, 0);
+		}
+	}
+	if(flags['o'])
+		stars();
+	if(flags['a'])
+		satels();
+	evflush();
+}
blob - /dev/null
blob + b8a71f36871ac0d90d6f89746ebf66ca67d0511e (mode 644)
--- /dev/null
+++ src/cmd/astro/star.c
@@ -0,0 +1,86 @@
+#include "astro.h"
+
+void
+star(void)
+{
+	double xm, ym, zm, dxm, dym, dzm;
+	double xx, yx, zx, yy, zy, zz, tau;
+	double capt0, capt1, capt12, capt13, sl, sb, cl;
+
+/*
+ *	remove E-terms of aberration
+ *	except when finding catalog mean places
+ */
+
+	alpha += (.341/(3600.*15.))*sin((alpha+11.26)*15.*radian)
+		  /cos(delta*radian);
+	delta += (.341/3600.)*cos((alpha+11.26)*15.*radian)
+		  *sin(delta*radian) - (.029/3600.)*cos(delta*radian);
+
+/*
+ *	correct for proper motion
+ */
+
+	tau = (eday - epoch)/365.24220;
+	alpha += tau*da/3600.;
+	delta += tau*dd/3600.;
+	alpha *= 15.*radian;
+	delta *= radian;
+
+/*
+ *	convert to rectangular coordinates merely for convenience
+ */
+
+	xm = cos(delta)*cos(alpha);
+	ym = cos(delta)*sin(alpha);
+	zm = sin(delta);
+
+/*
+ *	convert mean places at epoch of startable to current
+ *	epoch (i.e. compute relevant precession)
+ */
+
+	capt0 = (epoch - 18262.427)/36524.220e0;
+	capt1 = (eday - epoch)/36524.220;
+	capt12 = capt1*capt1;
+	capt13 = capt12*capt1;
+
+	xx = - (.00029696+26.e-8*capt0)*capt12
+		  - 13.e-8*capt13;
+	yx =  -(.02234941+1355.e-8*capt0)*capt1
+		  - 676.e-8*capt12 + 221.e-8*capt13;
+	zx = -(.00971690-414.e-8*capt0)*capt1
+		  + 207.e-8*capt12 + 96.e-8*capt13;
+	yy = - (.00024975+30.e-8*capt0)*capt12
+		  - 15.e-8*capt13;
+	zy = -(.00010858+2.e-8*capt0)*capt12;
+	zz = - (.00004721-4.e-8*capt0)*capt12;
+
+	dxm =  xx*xm + yx*ym + zx*zm;
+	dym = - yx*xm + yy*ym + zy*zm;
+	dzm = - zx*xm + zy*ym + zz*zm;
+
+	xm = xm + dxm;
+	ym = ym + dym;
+	zm = zm + dzm;
+
+/*
+ *	convert to mean ecliptic system of date
+ */
+
+	alpha = atan2(ym, xm);
+	delta = atan2(zm, sqrt(xm*xm+ym*ym));
+	cl = cos(delta)*cos(alpha);
+	sl = cos(delta)*sin(alpha)*cos(obliq) + sin(delta)*sin(obliq);
+	sb = -cos(delta)*sin(alpha)*sin(obliq) + sin(delta)*cos(obliq);
+	lambda = atan2(sl, cl);
+	beta = atan2(sb, sqrt(cl*cl+sl*sl));
+	rad = 1.e9;
+	if(px != 0)
+		rad = 20600/px;
+	motion = 0;
+	semi = 0;
+
+	helio();
+	geo();
+}
blob - /dev/null
blob + 52800f42ff19566068efe5512216d0430232073b (mode 644)
--- /dev/null
+++ src/cmd/astro/stars.c
@@ -0,0 +1,104 @@
+#include "astro.h"
+
+char*	startab = SYS9 "/lib/sky/estartab";
+
+void
+stars(void)
+{
+	double lomoon, himoon, sd;
+	int wrap, f, i;
+	char *saop;
+	static char saoa[100];
+
+	sd = 1000*radsec;
+	lomoon = omoon.point[0].ra - sd;
+	if(lomoon < 0)
+		lomoon += pipi;
+	himoon = omoon.point[NPTS+1].ra + sd;
+	if(himoon > pipi)
+		himoon -= pipi;
+	lomoon *= 12/pi;
+	himoon *= 12/pi;
+	wrap = 0;
+	if(lomoon > himoon)
+		wrap++;
+
+	f = open(startab, OREAD);
+	if(f < 0) {
+		fprint(2, "%s?\n", startab);
+		return;
+	}
+	epoch = 1950.0;
+	epoch = (epoch-1900.0) * 365.24220 + 0.313;
+	saop = saoa;
+
+/*
+ *	read mean places of stars at epoch of star table
+ */
+
+loop:
+	if(rline(f)) {
+		close(f);
+		return;
+	}
+	rah = atof(line+17);
+	ram = atof(line+20);
+	ras = atof(line+23);
+
+	alpha = rah + ram/60 + ras/3600;
+	if(wrap == 0) {
+		if(alpha < lomoon || alpha > himoon)
+			goto loop;
+	} else
+		if(alpha < lomoon && alpha > himoon)
+			goto loop;
+
+	sao = atof(line+0);
+	sprint(saop, "%ld", sao);
+	da = atof(line+30);
+	dday = atof(line+37);
+	dmin = atof(line+41);
+	dsec = atof(line+44);
+	dd = atof(line+50);
+	px = atof(line+57);
+	mag = atof(line+61);
+
+/*
+ *	convert rt ascension and declination to internal format
+ */
+
+	delta = fabs(dday) + dmin/60 + dsec/3600;
+	if(dday < 0)
+		delta = -delta;
+
+	star();
+/*
+ *	if(fabs(beta) > 6.55*radian)
+ *		goto loop;
+ */
+	sd = .0896833e0*cos(beta)*sin(lambda-1.3820+.00092422117*eday)
+		 + 0.99597*sin(beta);
+	if(fabs(sd) > .0183)
+		goto loop;
+
+	for(i=0; i<=NPTS+1; i++)
+		setobj(&ostar.point[i]);
+
+	occult(&omoon, &ostar, 0);
+	if(occ.t1 >= 0 || occ.t5 >= 0) {
+		i = PTIME;
+		if(mag > 2)
+			i |= DARK;
+		if(mag < 5)
+			i |= SIGNIF;
+		if(occ.t1 >= 0 && occ.e1 >= 0)
+			event("Occultation of SAO %s begins at ",
+				saop, "", occ.t1, i);
+		if(occ.t5 >= 0 && occ.e5 >= 0)
+			event("Occultation of SAO %s ends at ",
+				saop, "", occ.t5, i);
+		while(*saop++)
+			;
+	}
+	goto loop;
+}
blob - /dev/null
blob + 8821121c925b30d5b584e1e4ba4b03788317bdc3 (mode 644)
--- /dev/null
+++ src/cmd/astro/sun.c
@@ -0,0 +1,94 @@
+#include "astro.h"
+
+void
+sun(void)
+{
+	double mven, merth, mmars, mjup, msat;
+	double dmoon, mmoon, gmoon;
+	double pturbb, pturbl, pturbr, lograd;
+
+	ecc = .01675104 - 4.180e-5 * capt - 1.26e-7*capt2;
+	incl = 0;
+	node = 0;
+	argp = 281.220833 + .0000470684*eday + .000453*capt2
+		 + .000003*capt3;
+	mrad = 1;
+	anom = 358.475845 + .9856002670*eday - .000150*capt2
+		 - .000003*capt3;
+	motion = .9856473354;
+
+	dmoon = 350.737681+12.1907491914*eday-.001436*capt2;
+	gmoon = 11.250889 + 13.2293504490*eday - .003212*capt2;
+	mmoon = 296.104608 + 13.0649924465*eday + 9.192e-3*capt2;
+	mven  = 212.448 + 1.602121635*eday;
+	merth = 358.476 + 0.985600267*eday;
+	mmars = 319.590 + .524024095*eday;
+	mjup = 225.269 + .083082362*eday;
+	msat  = 175.593 + .033450794*eday;
+
+	dmoon = fmod(dmoon, 360.)*radian;
+	gmoon = fmod(gmoon, 360.)*radian;
+	mmoon = fmod(mmoon, 360.)*radian;
+	mven  *= radian;
+	merth *= radian;
+	mmars *= radian;
+	mjup *= radian;
+	msat  *= radian;
+
+	icosadd(sunfp, suncp);
+	anom += cosadd(4, mmars, merth, mven, mjup)/3600.;
+	anom += sinadd(5, mmars, merth, mven, mjup, .07884*capt)/3600.;
+
+	incl *= radian;
+	node *= radian;
+	argp *= radian;
+	anom = fmod(anom, 360.)*radian;
+
+/*
+ *	computation of elliptic orbit
+ */
+
+	lambda = anom + argp;
+
+	pturbl = (6910.057 - 17.240*capt - 0.052*capt2)*sin(anom)
+		 + (72.338 - 0.361*capt) * sin(2.*anom)
+		 + (1.054 - 0.001*capt) * sin(3.*anom)
+		 + 0.018 * sin(4.*anom);
+
+	lambda += pturbl*radsec;
+
+	beta = 0.;
+
+	lograd = (30.57e-6 - 0.15e-6*capt)
+		 - (7274.12e-6 - 18.14e-6*capt - 0.05e-6*capt2)*cos(anom)
+		 - (91.38e-6 - 0.46e-6*capt) * cos(2.*anom)
+		 - (1.45e-6 - 0.01e-6*capt) * cos(3.*anom)
+		 - 0.02e-6 * cos(4.*anom);
+
+	pturbl = cosadd(5, mmars, merth, mven, mjup, msat);
+	pturbl += sinadd(3, dmoon, mmoon, merth) + .9;
+	pturbl *= radsec;
+
+	pturbb =  cosadd(3, merth, mven, mjup);
+	pturbb += sinadd(3, gmoon, mmoon, dmoon);
+	pturbb *= radsec;
+
+	pturbr =  cosadd(5, mmars, merth, mven, mjup, msat);
+	pturbr += cosadd(3, dmoon, mmoon, merth);
+
+	lambda += pturbl;
+	if(lambda > pipi)
+		lambda -= pipi;
+
+	beta += pturbb;
+
+	lograd = (lograd+pturbr) * 2.30258509;
+	rad = 1 + lograd * (1 + lograd * (.5 + lograd/6));
+
+	motion *= radian*mrad*mrad/(rad*rad);
+
+	semi = 961.182;
+	if(flags['o'])
+		semi = 959.63;
+	mag = -26.5;
+}
blob - /dev/null
blob + 7f452bcfcf73786a0493311256975ff62293c14c (mode 644)
--- /dev/null
+++ src/cmd/astro/sunt.c
@@ -0,0 +1,242 @@
+#include "astro.h"
+
+double	sunfp[]	=
+{
+	-.265, 0,
+	3.760, 0,
+	 .200, 0,
+	0,
+
+	-.021, 0,
+	5.180, 0,
+	1.882, 3.8991,
+	-.030, 0,
+	0,
+
+	0.075, 5.1766,
+	4.838, 5.2203,
+	0.074, 3.6285,
+	0.116, 2.5988,
+	5.526, 2.5885,
+	2.497, 5.5143,
+	0.044, 5.4350,
+	0.666, 3.1016,
+	1.559, 6.0258,
+	1.024, 5.5527,
+	0.210, 3.5989,
+	0.144, 3.4104,
+	0.152, 6.0004,
+	0.084, 4.1120,
+	0.037, 3.8711,
+	0.123, 3.4086,
+	0.154, 6.2762,
+	0.038, 4.6094,
+	0.020, 5.1313,
+	0.042, 4.5239,
+	0.032, 0.8517,
+	0.273, 3.7996,
+	0.048, 4.5431,
+	0.041, 6.0388,
+	2.043, 6.0020,
+	1.770, 3.4977,
+	0.028, 2.5831,
+	0.129, 5.1348,
+	0.425, 5.9146,
+	0.034, 1.2391,
+	0.500, 1.8357,
+	0.585, 5.8304,
+	0.085, 0.9529,
+	0.204, 1.7593,
+	0.020, 3.2463,
+	0.154, 3.9689,
+	0.101, 1.6808,
+	0.049, 3.0805,
+	0.106, 3.8868,
+	0.052, 6.0895,
+	0.021, 3.7559,
+	0.028, 5.2011,
+	0.062, 6.0388,
+	0.044, 1.8483,
+	0.045, 3.9759,
+	0.021, 5.3931,
+	0.026, 1.9722,
+	0.163, 3.4662,
+	7.208, 3.1334,
+	2.600, 4.5940,
+	0.073, 4.8223,
+	0.069, 1.4102,
+	2.731, 1.5210,
+	1.610, 1.9110,
+	0.073, 4.4087,
+	0.164, 2.9758,
+	0.556, 1.4425,
+	0.210, 1.7261,
+	0.044, 2.9356,
+	0.080, 1.3561,
+	0.419, 1.7555,
+	0.320, 4.7030,
+	0.108, 5.0719,
+	0.112, 5.1243,
+	0.021, 5.0440,
+	0,
+
+	6.454, 0,
+	0.177, 0,
+	-.424, 0,
+	0.039, 0,
+	-.064, 0,
+	0.172, 0,
+	0,
+
+	-.092, 1.6354,
+	-.067, 2.1468,
+	-.210, 2.6494,
+	-.166, 4.6338,
+	0,
+
+	0.576, 0,
+	-.047, 0,
+	0.021, 0,
+	0,
+
+	2.359e-6, 3.6607,
+	6.842e-6, 1.0180,
+	0.869e-6, 3.9567,
+	1.045e-6, 1.5332,
+	1.497e-6, 4.4691,
+	0.376e-6, 2.0295,
+	2.057e-6, 4.0941,
+	0.215e-6, 4.3459,
+	0.478e-6, 0.2648,
+	0.208e-6, 1.9548,
+	7.067e-6, 1.5630,
+	0.244e-6, 5.9097,
+	4.026e-6, 6.2526,
+	1.459e-6, 0.3409,
+	0.281e-6, 1.4172,
+	0.803e-6, 6.1533,
+	0.429e-6, 0.1850,
+	0,
+
+	13.36e-6, 0,
+	-1.33e-6, 0,
+	 0.37e-6, 0,
+	 0.36e-6, 0,
+	0,
+};
+char	suncp[]	=
+{
+	4, -7, 3, 0,
+	-8, 4, 0, 3,
+	15, -8, 0, 0,
+
+	4, -7, 3, 0, 0,
+	-8, 4, 0, 3, 0,
+	0, 13, -8, 0, 1,
+	15, -8, 0, 0, 0,
+
+	0,0,1,0,0,
+	0,-1,1,0,0,
+	0,-2,1,0,0,
+	0,-1,2,0,0,
+	0,-2,2,0,0,
+	0,-3,2,0,0,
+	0,-4,2,0,0,
+	0,-3,3,0,0,
+	0,-4,3,0,0,
+	0,-5,3,0,0,
+	0,-4,4,0,0,
+	0,-5,4,0,0,
+	0,-6,4,0,0,
+	0,-5,5,0,0,
+	0,-6,5,0,0,
+	0,-7,5,0,0,
+	0,-8,5,0,0,
+	0,-6,6,0,0,
+	0,-7,7,0,0,
+	0,-12,8,0,0,
+	0,-14,8,0,0,
+	-1,1,0,0,0,
+	-1,0,0,0,0,
+	-2,3,0,0,0,
+	-2,2,0,0,0,
+	-2,1,0,0,0,
+	-2,0,0,0,0,
+	-3,3,0,0,0,
+	-3,2,0,0,0,
+	-4,4,0,0,0,
+	-4,3,0,0,0,
+	-4,2,0,0,0,
+	-5,4,0,0,0,
+	-5,3,0,0,0,
+	-6,5,0,0,0,
+	-6,4,0,0,0,
+	-6,3,0,0,0,
+	-7,5,0,0,0,
+	-7,4,0,0,0,
+	-8,5,0,0,0,
+	-8,4,0,0,0,
+	-9,6,0,0,0,
+	-9,5,0,0,0,
+	-11,6,0,0,0,
+	-13,7,0,0,0,
+	-15,9,0,0,0,
+	-17,9,0,0,0,
+	0,2,0,-1,0,
+	0,1,0,-1,0,
+	0,0,0,-1,0,
+	0,-1,0,-1,0,
+	0,3,0,-2,0,
+	0,2,0,-2,0,
+	0,1,0,-2,0,
+	0,0,0,-2,0,
+	0,3,0,-3,0,
+	0,2,0,-3,0,
+	0,1,0,-3,0,
+	0,3,0,-4,0,
+	0,2,0,-4,0,
+	0,1,0,0,-1,
+	0,0,0,0,-1,
+	0,2,0,0,-2,
+	0,1,0,0,-2,
+	0,2,0,0,-3,
+
+	1,0,0,
+	1,1,0,
+	1,-1,0,
+	3,-1,0,
+	1,0,1,
+	1,0,-1,
+
+	-2,1,0,
+	-3,2,0,
+	-4,2,0,
+	1,0,-2,
+
+	1,0,0,
+	1,-1,0,
+	-1,0,2,
+
+	0,-1,1,0,0,
+	0,-2,2,0,0,
+	0,-3,2,0,0,
+	0,-3,3,0,0,
+	0,-4,3,0,0,
+	0,-4,4,0,0,
+	-2,2,0,0,0,
+	-3,2,0,0,0,
+	-4,3,0,0,0,
+	0,2,0,-1,0,
+	0,1,0,-1,0,
+	0,0,0,-1,0,
+	0,2,0,-2,0,
+	0,1,0,-2,0,
+	0,3,0,-3,0,
+	0,2,0,-3,0,
+	0,1,0,0,-1,
+
+	1,0,0,
+	1,-1,0,
+	1,1,0,
+	1,0,-1,
+};
blob - /dev/null
blob + b40fabe10c15c9fc4950ea542ed63e9f10492a47 (mode 644)
--- /dev/null
+++ src/cmd/astro/uran.c
@@ -0,0 +1,154 @@
+#include "astro.h"
+
+static	double	elem[] =
+{
+	36525.0,		// [0] eday of epoc
+
+	19.19126393,		// [1] semi major axis (au)
+	0.04716771,		// [2] eccentricity
+ 	0.76986,		// [3] inclination (deg)
+	74.22988,		// [4] longitude of the ascending node (deg)
+	170.96424,		// [5] longitude of perihelion (deg)
+	313.23218,		// [6] mean longitude (deg)
+
+	0.00152025,		// [1+6] (au/julian century)
+	-0.00019150,		// [2+6] (e/julian century)
+  	-2.09,			// [3+6] (arcsec/julian century)
+	-1681.40,		// [4+6] (arcsec/julian century)
+	1312.56,		// [5+6] (arcsec/julian century)
+	1542547.79,		// [6+6] (arcsec/julian century)
+};
+
+void
+uran(void)
+{
+	double pturbl, pturbb, pturbr;
+	double lograd;
+	double dele, enom, vnom, nd, sl;
+
+	double capj, capn, eye, comg, omg;
+	double sb, su, cu, u, b, up;
+	double sd, ca, sa;
+
+	double cy;
+
+	cy = (eday - elem[0]) / 36525.;		// per julian century
+
+	mrad = elem[1] + elem[1+6]*cy;
+	ecc = elem[2] + elem[2+6]*cy;
+
+	cy = cy / 3600;				// arcsec/deg per julian century
+	incl = elem[3] + elem[3+6]*cy;
+	node = elem[4] + elem[4+6]*cy;
+	argp = elem[5] + elem[5+6]*cy;
+
+	anom = elem[6] + elem[6+6]*cy - argp;
+	motion = elem[6+6] / 36525. / 3600;
+
+	incl *= radian;
+	node *= radian;
+	argp *= radian;
+	anom = fmod(anom,360.)*radian;
+
+	enom = anom + ecc*sin(anom);
+	do {
+		dele = (anom - enom + ecc * sin(enom)) /
+			(1. - ecc*cos(enom));
+		enom += dele;
+	} while(fabs(dele) > converge);
+	vnom = 2.*atan2(sqrt((1.+ecc)/(1.-ecc))*sin(enom/2.),
+		cos(enom/2.));
+	rad = mrad*(1. - ecc*cos(enom));
+
+	lambda = vnom + argp;
+	pturbl = 0.;
+	lambda += pturbl*radsec;
+	pturbb = 0.;
+	pturbr = 0.;
+
+/*
+ *	reduce to the ecliptic
+ */
+
+	nd = lambda - node;
+	lambda = node + atan2(sin(nd)*cos(incl),cos(nd));
+
+	sl = sin(incl)*sin(nd) + pturbb*radsec;
+	beta = atan2(sl, pyth(sl));
+
+	lograd = pturbr*2.30258509;
+	rad *= 1. + lograd;
+
+
+	lambda -= 1185.*radsec;
+	beta -= 51.*radsec;
+
+	motion *= radian*mrad*mrad/(rad*rad);
+	semi = 83.33;
+
+/*
+ *	here begins the computation of magnitude
+ *	first find the geocentric equatorial coordinates of Saturn
+ */
+
+	sd = rad*(cos(beta)*sin(lambda)*sin(obliq) +
+		sin(beta)*cos(obliq));
+	sa = rad*(cos(beta)*sin(lambda)*cos(obliq) -
+		sin(beta)*sin(obliq));
+	ca = rad*cos(beta)*cos(lambda);
+	sd += zms;
+	sa += yms;
+	ca += xms;
+	alpha = atan2(sa,ca);
+	delta = atan2(sd,sqrt(sa*sa+ca*ca));
+
+/*
+ *	here are the necessary elements of Saturn's rings
+ *	cf. Exp. Supp. p. 363ff.
+ */
+
+	capj = 6.9056 - 0.4322*capt;
+	capn = 126.3615 + 3.9894*capt + 0.2403*capt2;
+	eye = 28.0743 - 0.0128*capt;
+	comg = 168.1179 + 1.3936*capt;
+	omg = 42.9236 - 2.7390*capt - 0.2344*capt2;
+
+	capj *= radian;
+	capn *= radian;
+	eye *= radian;
+	comg *= radian;
+	omg *= radian;
+
+/*
+ *	now find saturnicentric ring-plane coords of the earth
+ */
+
+	sb = sin(capj)*cos(delta)*sin(alpha-capn) -
+		cos(capj)*sin(delta);
+	su = cos(capj)*cos(delta)*sin(alpha-capn) +
+		sin(capj)*sin(delta);
+	cu = cos(delta)*cos(alpha-capn);
+	u = atan2(su,cu);
+	b = atan2(sb,sqrt(su*su+cu*cu));
+
+/*
+ *	and then the saturnicentric ring-plane coords of the sun
+ */
+
+	su = sin(eye)*sin(beta) +
+		cos(eye)*cos(beta)*sin(lambda-comg);
+	cu = cos(beta)*cos(lambda-comg);
+	up = atan2(su,cu);
+
+/*
+ *	at last, the magnitude
+ */
+
+
+	sb = sin(b);
+	mag = -8.68 +2.52*fabs(up+omg-u)-
+		2.60*fabs(sb) + 1.25*(sb*sb);
+
+	helio();
+	geo();
+}
blob - /dev/null
blob + 7ee1146dc29f534e056bdea4e77de2b8e92c77ce (mode 644)
--- /dev/null
+++ src/cmd/astro/venus.c
@@ -0,0 +1,126 @@
+#include "astro.h"
+
+
+void
+venus(void)
+{
+	double pturbl, pturbb, pturbr;
+	double lograd;
+	double dele, enom, vnom, nd, sl;
+	double v0, t0, m0, j0, s0;
+	double lsun, elong, ci, dlong;
+
+/*
+ *	here are the mean orbital elements
+ */
+
+	ecc = .00682069 - .00004774*capt + 0.091e-6*capt2;
+	incl = 3.393631 + .0010058*capt - 0.97e-6*capt2;
+	node = 75.779647 + .89985*capt + .00041*capt2;
+	argp = 130.163833 + 1.408036*capt - .0009763*capt2;
+	mrad = .7233316;
+	anom = 212.603219 + 1.6021301540*eday + .00128605*capt2;
+	motion = 1.6021687039;
+
+/*
+ *	mean anomalies of perturbing planets
+ */
+
+	v0 = 212.60 + 1.602130154*eday;
+	t0 = 358.63  + .985608747*eday;
+	m0 = 319.74 + 0.524032490*eday;
+	j0 = 225.43 + .083090842*eday;
+	s0 = 175.8  + .033459258*eday;
+
+	v0 *= radian;
+	t0 *= radian;
+	m0 *= radian;
+	j0 *= radian;
+	s0 *= radian;
+
+	incl *= radian;
+	node *= radian;
+	argp *= radian;
+	anom = fmod(anom, 360.)*radian;
+
+/*
+ *	computation of long period terms affecting the mean anomaly
+ */
+
+	anom +=
+		   (2.761-0.022*capt)*radsec*sin(
+		  13.*t0 - 8.*v0 + 43.83*radian + 4.52*radian*capt)
+		 + 0.268*radsec*cos(4.*m0 - 7.*t0 + 3.*v0)
+		 + 0.019*radsec*sin(4.*m0 - 7.*t0 + 3.*v0)
+		 - 0.208*radsec*sin(s0 + 1.4*radian*capt);
+
+/*
+ *	computation of elliptic orbit
+ */
+
+	enom = anom + ecc*sin(anom);
+	do {
+		dele = (anom - enom + ecc * sin(enom)) /
+			(1 - ecc*cos(enom));
+		enom += dele;
+	} while(fabs(dele) > converge);
+	vnom = 2*atan2(sqrt((1+ecc)/(1-ecc))*sin(enom/2),
+		cos(enom/2));
+	rad = mrad*(1 - ecc*cos(enom));
+
+	lambda = vnom + argp;
+
+/*
+ *	perturbations in longitude
+ */
+
+	icosadd(venfp, vencp);
+	pturbl = cosadd(4, v0, t0, m0, j0);
+	pturbl *= radsec;
+
+/*
+ *	perturbations in latidude
+ */
+
+	pturbb = cosadd(3, v0, t0, j0);
+	pturbb *= radsec;
+
+/*
+ *	perturbations in log radius vector
+ */
+
+	pturbr = cosadd(4, v0, t0, m0, j0);
+
+/*
+ *	reduction to the ecliptic
+ */
+
+	lambda += pturbl;
+	nd = lambda - node;
+	lambda = node + atan2(sin(nd)*cos(incl),cos(nd));
+
+	sl = sin(incl)*sin(nd);
+	beta = atan2(sl, pyth(sl)) + pturbb;
+
+	lograd = pturbr*2.30258509;
+	rad *= 1 + lograd;
+
+
+	motion *= radian*mrad*mrad/(rad*rad);
+
+/*
+ *	computation of magnitude
+ */
+
+	lsun = 99.696678 + 0.9856473354*eday;
+	lsun *= radian;
+	elong = lambda - lsun;
+	ci = (rad - cos(elong))/sqrt(1 + rad*rad - 2*rad*cos(elong));
+	dlong = atan2(pyth(ci), ci)/radian;
+	mag = -4 + .01322*dlong + .0000004247*dlong*dlong*dlong;
+
+	semi = 8.41;
+
+	helio();
+	geo();
+}
blob - /dev/null
blob + a4521af60f6c40ef607f6f0bbd19c72377c4052f (mode 644)
--- /dev/null
+++ src/cmd/astro/venust.c
@@ -0,0 +1,60 @@
+#include "astro.h"
+
+double	venfp[]	=
+{
+	4.889,		2.0788,
+	11.261,		2.5870,
+	7.128,		6.2384,
+	3.446,		2.3721,
+	1.034,		0.4632,
+	1.575,		3.3847,
+	1.439,		2.4099,
+	1.208,		4.1464,
+	2.966,		3.6318,
+	1.563,		4.6829,
+	0.,
+	0.122,		4.2726,
+	0.300,		0.0218,
+	0.159,		1.3491,
+	0.,
+	2.246e-6,	0.5080,
+	9.772e-6,	1.0159,
+	8.271e-6,	4.6674,
+	0.737e-6,	0.8267,
+	1.426e-6,	5.1747,
+	0.510e-6,	5.7009,
+	1.572e-6,	1.8188,
+	0.717e-6,	2.2969,
+	2.991e-6,	2.0611,
+	1.335e-6,	0.9628,
+	0.,
+};
+
+char	vencp[]	=
+{
+	1,-1,0,0,
+	2,-2,0,0,
+	3,-3,0,0,
+	2,-3,0,0,
+	4,-4,0,0,
+	4,-5,0,0,
+	3,-5,0,0,
+	1,0,-3,0,
+	1,0,0,-1,
+	0,0,0,-1,
+
+	0,-1,0,
+	4,-5,0,
+	1,0,-2,
+
+	1,-1,0,0,
+	2,-2,0,0,
+	3,-3,0,0,
+	2,-3,0,0,
+	4,-4,0,0,
+	5,-5,0,0,
+	4,-5,0,0,
+	2,0,-3,0,
+	1,0,0,-1,
+	2,0,0,-2,
+};