-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscales.hpp
More file actions
205 lines (158 loc) · 7.34 KB
/
scales.hpp
File metadata and controls
205 lines (158 loc) · 7.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
#pragma once
/**
* @file scales.hpp
* @brief Time-scale tag types and traits for the tempoch Time<S> template.
*
* Mirrors the Rust `tempoch_core::scales` module. Each tag is an empty struct
* that selects the FFI functions used by `Time<S>`.
*
* Adding a new scale requires:
* 1. Define a tag struct (e.g. `struct TTScale {};`).
* 2. Specialise `TimeScaleTraits<TTScale>` with the FFI calls.
* 3. Specialise `TimeConvertTraits<A,B>` for each supported conversion pair.
*/
#include "ffi_core.hpp" // tempoch_ffi.h + check_status
namespace tempoch {
// Forward declaration — defined in time_base.hpp.
struct CivilTime;
// ============================================================================
// Scale Tags
// ============================================================================
/// Julian Date (days since −4712‑01‑01T12:00 TT).
struct JDScale {};
/// Modified Julian Date (JD − 2 400 000.5).
struct MJDScale {};
/// UTC, internally stored as MJD days for arithmetic.
struct UTCScale {};
// Stubs for future FFI-backed scales — uncomment and specialise traits once
// the FFI exposes the conversion functions.
// struct TTScale {}; // Terrestrial Time
// struct TAIScale {}; // International Atomic Time
// struct TDBScale {}; // Barycentric Dynamical Time
// struct TCGScale {}; // Geocentric Coordinate Time
// struct TCBScale {}; // Barycentric Coordinate Time
// struct GPSScale {}; // GPS Time
// struct UTScale {}; // Universal Time (UT1)
// ============================================================================
// TimeScaleTraits — per-scale FFI dispatch
// ============================================================================
/**
* @brief Primary template — must be specialised for every supported scale.
*
* Required static members:
* - `const char* label()`
* - `double from_utc(const CivilTime&)` — civil time → raw days
* - `CivilTime to_utc(double days)` — raw days → civil time
* - `double add_days(double days, double delta)`
* - `double difference(double a, double b)` — a − b in days
*/
template <typename S> struct TimeScaleTraits {
static_assert(sizeof(S) == 0,
"TimeScaleTraits<S> must be specialised for this scale.");
};
// ── JDScale ─────────────────────────────────────────────────────────────────
template <> struct TimeScaleTraits<JDScale> {
static constexpr const char *label() { return "JD"; }
static double from_civil(const CivilTime &ct);
static CivilTime to_civil(double jd);
static double add_days(double jd, double delta) {
return tempoch_jd_add_days(jd, delta);
}
static double difference(double a, double b) {
return tempoch_jd_difference(a, b);
}
/// Difference as a typed `qtty_quantity_t` (Day unit).
static qtty_quantity_t difference_qty(double a, double b) {
return tempoch_jd_difference_qty(a, b);
}
/// Add a typed duration quantity and write result to @p out.
static void add_qty(double jd, qtty_quantity_t duration, double &out) {
check_status(tempoch_jd_add_qty(jd, duration, &out), "Time<JD>::add_qty");
}
/// J2000.0 epoch constant (JD 2 451 545.0).
static double j2000() { return tempoch_jd_j2000(); }
/// Julian centuries elapsed since J2000.
static double julian_centuries(double jd) {
return tempoch_jd_julian_centuries(jd);
}
/// Julian centuries since J2000 as a typed `qtty_quantity_t`
/// (JulianCentury unit).
static qtty_quantity_t julian_centuries_qty(double jd) {
return tempoch_jd_julian_centuries_qty(jd);
}
};
// ── MJDScale ────────────────────────────────────────────────────────────────
template <> struct TimeScaleTraits<MJDScale> {
static constexpr const char *label() { return "MJD"; }
static double from_civil(const CivilTime &ct);
static CivilTime to_civil(double mjd);
static double add_days(double mjd, double delta) {
return tempoch_mjd_add_days(mjd, delta);
}
static double difference(double a, double b) {
return tempoch_mjd_difference(a, b);
}
/// Difference as a typed `qtty_quantity_t` (Day unit).
static qtty_quantity_t difference_qty(double a, double b) {
return tempoch_mjd_difference_qty(a, b);
}
/// Add a typed duration quantity and write result to @p out.
static void add_qty(double mjd, qtty_quantity_t duration, double &out) {
check_status(tempoch_mjd_add_qty(mjd, duration, &out),
"Time<MJD>::add_qty");
}
};
// ── UTCScale (internally stored as MJD) ─────────────────────────────────────
template <> struct TimeScaleTraits<UTCScale> {
static constexpr const char *label() { return "UTC"; }
static double from_civil(const CivilTime &ct);
static CivilTime to_civil(double mjd);
static double add_days(double mjd, double delta) {
return tempoch_mjd_add_days(mjd, delta);
}
static double difference(double a, double b) {
return tempoch_mjd_difference(a, b);
}
/// Difference as a typed `qtty_quantity_t` (Day unit).
static qtty_quantity_t difference_qty(double a, double b) {
return TimeScaleTraits<MJDScale>::difference_qty(a, b);
}
/// Add a typed duration quantity and write result to @p out.
static void add_qty(double mjd, qtty_quantity_t duration, double &out) {
TimeScaleTraits<MJDScale>::add_qty(mjd, duration, out);
}
};
// ============================================================================
// TimeConvertTraits — cross-scale conversion
// ============================================================================
/**
* @brief Primary template — specialise for each supported A→B pair.
*
* Required: `static double convert(double src_days)`.
*/
template <typename From, typename To> struct TimeConvertTraits {
static_assert(sizeof(From) == 0,
"TimeConvertTraits<From,To> is not specialised for this pair.");
};
// ── JD ↔ MJD ────────────────────────────────────────────────────────────────
template <> struct TimeConvertTraits<JDScale, MJDScale> {
static double convert(double jd) { return tempoch_jd_to_mjd(jd); }
};
template <> struct TimeConvertTraits<MJDScale, JDScale> {
static double convert(double mjd) { return tempoch_mjd_to_jd(mjd); }
};
// ── JD ↔ UTC (UTC stored as MJD internally) ────────────────────────────────
template <> struct TimeConvertTraits<JDScale, UTCScale> {
static double convert(double jd) { return tempoch_jd_to_mjd(jd); }
};
template <> struct TimeConvertTraits<UTCScale, JDScale> {
static double convert(double mjd) { return tempoch_mjd_to_jd(mjd); }
};
// ── MJD ↔ UTC (identity — both stored as MJD) ──────────────────────────────
template <> struct TimeConvertTraits<MJDScale, UTCScale> {
static double convert(double mjd) { return mjd; }
};
template <> struct TimeConvertTraits<UTCScale, MJDScale> {
static double convert(double mjd) { return mjd; }
};
} // namespace tempoch