From 0ed29b9ea78f7f3cb8e997fbc2e8c3c297e61eef Mon Sep 17 00:00:00 2001 From: Attila Kovacs Date: Mon, 30 Dec 2024 09:28:36 +0100 Subject: [PATCH] Move readeph0.c to examples/ --- CHANGELOG.md | 7 ++- examples/readeph0.c | 112 +++++++++++++++++++++++++++++++++++++++++ include/solarsystem.h | 11 ++-- src/readeph0.c | 56 --------------------- test/Makefile | 2 +- test/src/test-errors.c | 6 ++- 6 files changed, 130 insertions(+), 64 deletions(-) create mode 100644 examples/readeph0.c delete mode 100644 src/readeph0.c diff --git a/CHANGELOG.md b/CHANGELOG.md index eace8b6d..cb9669ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,8 +16,8 @@ Release candidate for the next feature release, expected around 1 February 2025. - Fixes to GCC version checking for macros. - - Fixed dummy `readeph()` implementation in `readeph0.c`, and `DEFAULT_READEPH` in `config.mk`. `readeph0.c` is not - linked by default, and was not linked in prior releases either. + - Fixed dummy `readeph()` implementation in `readeph0.c`, and the use of `DEFAULT_READEPH` in `config.mk`. `readeph0.c` + is not linked by default, and was not linked in prior releases either. ### Added @@ -119,6 +119,9 @@ Release candidate for the next feature release, expected around 1 February 2025. - Static library is now named `ibsupernovas.a`, which is symlinked to `libnovas.a` for back compatibility. + - `readeph0.c` moved to `examples/`. It's a dummy legacy NOVAS C implementation that is not really needed in + SuperNOVAS. + - Various small tweaks to Makefiles. - Updated `README.md` documentation. diff --git a/examples/readeph0.c b/examples/readeph0.c new file mode 100644 index 00000000..a1df147f --- /dev/null +++ b/examples/readeph0.c @@ -0,0 +1,112 @@ +/** + * @author G. Kaplan and A. Kovacs + * + * Dummy readeph() implementation for SuperNOVAS to use when minor planet ephemeris is + * unavailable, but you want the functionality to be present in name only. It's not really + * useful as an implementation as is, but it can be used as a basis for an actual legacy + * NOVAS C module. + * + * SuperNOVAS provides an improved method for setting more capable ephemeris provider + * functions dynamically, at runtime. So, unless you readily have a legacy readeph() + * implementation to use, we recommend you implement an novas_ephem_provider function, and + * activate it in your application with set_ephem_provider instead. + * + * Based on the NOVAS C Edition, Version 3.1: + * + * U. S. Naval Observatory
+ * Astronomical Applications Dept.
+ * Washington, DC
+ * + * http://www.usno.navy.mil/USNO/astronomical-applications + * + * + * @sa readeph() + * @sa set_ephem_provider() + * @sa novas_ephem_provider + */ +#include +#include + +/// \cond PRIVATE +#define __NOVAS_INTERNAL_API__ ///< Use definitions meant for internal use by SuperNOVAS only +/// \endcond + +#include "novas.h" + + +/** + * Returns a zeroed pv[] array, with an error code of 9 indicating that it's not real data. + * This is basically the NOVAS C 3.1 readeph0.c implementation with added comments and + * error handling. + * + * It can be used a a template for an actual implementation for minor planets, which are not + * handled by the solarsystem() type calls. You can set the built-in implementation for the + * library at build-time by setting the DEFAULT_READEPH variable in the `config.mk`. + * + * @param mp The ID number of the solar-system body for which the position are + * desired. An actual implementation might use this and/or the name to + * identify the object. + * @param name The name of the solar-system body (usually upper-case). An actual + * implementation might use this and/or `mp` to identify the object. + * @param jd_tdb [day] Barycentric Dynamical Time (TDB) based Julian date for which to + * find the position and velocity. + * @param[out] error Pointer to integer to populate with the error status: 0 if successful, + * -1 if any of the pointer arguments are NULL, or some non-zero value + * if the was an error s.t. the position and velocity vector should not + * be used, or else any non-zero value to indicate particular error + * conditions. + * @return [AU, AU/day] A newly allocated 6-vector in rectangular equatorial + * coordinates, containing the heliocentric position coordinates in AU, + * followed by hte heliocentric velocity components in AU/day. The caller + * is responsible for calling free() on the returned value when it is no + * longer needed. + * + * @sa readeph() + * @sa set_ephem_provider() + * @sa novas_ephem_provider + * @sa NOVAS_EPHEM_OBJECT + * + */ +double *readeph_dummy(int mp, const char *name, double jd_tdb, int *error) { + static const char *fn = "readeph_dummy"; + double *pv; + + // Check that pointers arguments are not NULL. + if(!name || !error) { + novas_set_errno(EINVAL, fn, "NULL parameter: name=%p, error=%p", name, error); + if(error) *error = -1; + return NULL; + } + + // Check that TDB is not NAN. + if(isnanf(jd_tdb)) { + novas_set_errno(EINVAL, fn, "NaN jd_tdb"); + *error = -1; + return NULL; + } + + // Dynamically allocated return value + pv = (double*) calloc(6, sizeof(double)); + if(pv) { + // An actual implementation would populate the position and velocity components + // of pv[] here, and set the value in error to 0 to indicate successful return + // or else to another appropriate value if no valid position / velocity vector + // is provided. + + // But since this is just a dummy example, with no really valid data, we'll + // set the value in error to the NOVAS C 3.1 legacy error code for readeph0.c + *error = 9; + } + else { + novas_set_errno(errno, fn, "alloc error"); + *error = -1; // allocation error. + } + + return pv; +} + +#ifdef DEFAULT_READEPH +double *readeph(int mp, const char *name, double jd_tdb, int *error) { + return readeph_dummy(mp, name, jd_tdb, error); +} +#endif diff --git a/include/solarsystem.h b/include/solarsystem.h index c18b8422..a51a7a9e 100644 --- a/include/solarsystem.h +++ b/include/solarsystem.h @@ -207,8 +207,8 @@ typedef int (*novas_ephem_provider)(const char *name, long id, double jd_tdb_hig * statically compiled readeph() implementation, or else a dynamically defined one via * ephemeris_set_reader(). * - * You can set the built-in implementation for the library by setting the DEFAULT_READEPH - * variable in the Makefile. + * You can set the built-in implementation for the library at build time by setting the + * DEFAULT_READEPH variable in the `config.mk`. * * @deprecated This old ephemeris reader is prone to memory leaks, and lacks some useful * functionality. Users are strongly encouraged to use the new @@ -216,8 +216,10 @@ typedef int (*novas_ephem_provider)(const char *name, long id, double jd_tdb_hig * implementations at runtime. * * @param mp The ID number of the solar-system body for which the position are - * desired. - * @param name The name of the solar-system body (usually upper-case) + * desired. An actual implementation might use this and/or the name to + * identify the object. + * @param name The name of the solar-system body (usually upper-case). An actual + * implementation might use this and/or `mp` to identify the object. * @param jd_tdb [day] Barycentric Dynamical Time (TDB) based Julian date for which to * find the position and velocity. * @param[out] error Pointer to integer to populate with the error status: 0 if successful, @@ -230,6 +232,7 @@ typedef int (*novas_ephem_provider)(const char *name, long id, double jd_tdb_hig * is responsible for calling free() on the returned value when it is no * longer needed. * + * @sa set_ephem_provider() * @sa novas_ephem_provider * @sa ephemeris() * @sa NOVAS_EPHEM_OBJECT diff --git a/src/readeph0.c b/src/readeph0.c deleted file mode 100644 index f605b7cc..00000000 --- a/src/readeph0.c +++ /dev/null @@ -1,56 +0,0 @@ -/** - * @author G. Kaplan and A. Kovacs - * - * Dummy readeph() implementation for SuperNOVAS for use when minor planet ephermeris is - * unavailable. - * - * Based on the NOVAS C Edition, Version 3.1: - * - * U. S. Naval Observatory
- * Astronomical Applications Dept.
- * Washington, DC
- * - * http://www.usno.navy.mil/USNO/astronomical-applications - * - */ -#include -#include - -/// \cond PRIVATE -#define __NOVAS_INTERNAL_API__ ///< Use definitions meant for internal use by SuperNOVAS only -/// \endcond - -#include "novas.h" - -double * readeph_dummy(int mp, const char *name, double jd_tdb, int *error) { - static const char *fn = "readeph_dummy"; - double *pv; - - if(!name || !error) { - novas_set_errno(EINVAL, fn, "NULL parameter: name=%p, error=%p", name, error); - if(error) *error = -1; - return NULL; - } - - if(isnanf(jd_tdb)) { - novas_set_errno(EINVAL, fn, "NaN jd_tdb"); - *error = -1; - return NULL; - } - - pv = (double*) calloc(6, sizeof(double)); - if(pv) *error = 0; - else *error = -1; - - return pv; -} - -#ifdef DEFAULT_READEPH -double *readeph(int mp, const char *name, double jd_tdb, int *error) { - return readeph_dummy(mp, name, jd_tdb, error); -} -#else -double * default_readeph(int mp, const char *name, double jd_tdb, int *error) { - return readeph_dummy(mp, name, jd_tdb, error); -} -#endif diff --git a/test/Makefile b/test/Makefile index da0c91fa..83d96415 100644 --- a/test/Makefile +++ b/test/Makefile @@ -12,7 +12,7 @@ LDFLAGS += -fprofile-arcs -ftest-coverage -lm include ../config.mk #OBJECTS := $(subst obj/,,$(OBJECTS)) -OBJECTS := novas.o nutation.o solsys3.o super.o frames.o timescale.o refract.o naif.o readeph0.o +OBJECTS := novas.o nutation.o solsys3.o super.o frames.o timescale.o refract.o naif.o TESTS := test-compat test-cio_file test-super test-errors COVFILES := novas.c.gcov nutation.c.gcov solsys3.c.gcov super.c.gcov timescale.c.gcov refract.c.gcov frames.c.gcov naif.c.gcov diff --git a/test/src/test-errors.c b/test/src/test-errors.c index 0d52b21f..18537b10 100644 --- a/test/src/test-errors.c +++ b/test/src/test-errors.c @@ -279,8 +279,10 @@ static int test_ephemeris() { if(check("ephemeris:pos+vel", -1, ephemeris(tdb, &ceres, NOVAS_BARYCENTER, NOVAS_FULL_ACCURACY, NULL, NULL))) n++; if(check("ephemeris:pos=vel", -1, ephemeris(tdb, &ceres, NOVAS_BARYCENTER, NOVAS_FULL_ACCURACY, p, p))) n++; if(check("ephemeris:origin", 1, ephemeris(tdb, &ceres, -1, NOVAS_FULL_ACCURACY, p, v))) n++; - if(check("ephemeris:noephem", -1, ephemeris(tdb, &ceres, NOVAS_BARYCENTER, NOVAS_FULL_ACCURACY, p, v))) n++; +#ifndef DEFAULT_READEPH + if(check("ephemeris:noephem", -1, ephemeris(tdb, &ceres, NOVAS_BARYCENTER, NOVAS_FULL_ACCURACY, p, v))) n++; +#endif return n; } @@ -1254,9 +1256,11 @@ static int test_geom_posvel() { frame.accuracy = 2; if(check("geom_posvel:frame:accuracy:2", -1, novas_geom_posvel(&o, &frame, NOVAS_ICRS, pos, vel))) n++; +#ifndef DEFAULT_READEPH frame.accuracy = NOVAS_REDUCED_ACCURACY; make_ephem_object("blah", 111111, &o); if(check("geom_posvel:ephem_object", -1, novas_geom_posvel(&o, &frame, NOVAS_ICRS, pos, vel))) n++; +#endif return n; }