commit d9b64d66ad39a77ac1d33102d1d367bade45beff
parent dd1f655189eb8ea5d5d683450f4d0f8d95350cd6
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Thu, 14 Aug 2025 14:18:50 +0200
Refactor time interval verification
Move the interval duration checks to a separate function to improve the
readability of the analysis code.
Comment on the lack of verification of the order of time intervals: this
is actually unnecessary, as verifying the duration of the intervals also
allows the chronological order to be verified.
Diffstat:
| M | src/smeteo_load.c | | | 92 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------- |
1 file changed, 66 insertions(+), 26 deletions(-)
diff --git a/src/smeteo_load.c b/src/smeteo_load.c
@@ -309,12 +309,59 @@ error:
}
static res_T
+check_interval_duration
+ (const struct smeteo* smeteo,
+ const struct txtrdr* txtrdr,
+ const size_t id, /* Index of the interval to check */
+ const double expected_duration) /* [day/1850] */
+{
+ const struct smeteo_entry* entries = NULL;
+ const double eps = expected_duration*1e-6;
+ double duration = 0;
+ res_T res = RES_OK;
+
+ ASSERT(smeteo && txtrdr && expected_duration > 0);
+ ASSERT(id < darray_entry_size_get(&smeteo->entries));
+
+ entries = darray_entry_cdata_get(&smeteo->entries);
+
+ if(id == 0) {
+ /* The dates of the intervals are relative to midnight on January 1, 1850.
+ * In addition, their time is defined at the center of the interval. Thus,
+ * for the first interval, calculate its duration by multiplying its date
+ * relative to January 1, 1850 by 2 */
+ duration = entries[0].day_1850*2;
+ } else {
+ duration = entries[id-0].day_1850 - entries[id-1].day_1850;
+ }
+
+ if(!eq_eps(duration, expected_duration, eps)) {
+ ERROR(smeteo,
+ "%s:%lu: invalid time interval. "
+ "It is calculated from the \"day_1850\" variables between consecutive "
+ "intervals. The interval duration must be constant, which is not the "
+ "case here. "
+ "Expected duration: %g [day/1850]; current duration: %g [day/1850] -- "
+ "%g != %g +/- %g [day/1850]\n",
+ txtrdr_get_name(txtrdr), txtrdr_get_line_num(txtrdr),
+ expected_duration, duration, expected_duration, duration, eps);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
load_stream(struct smeteo* smeteo, FILE* fp, const char* name)
{
struct txtrdr* txtrdr = NULL;
size_t i = 0;
size_t nintervals = 0;
- double interval_ref = -1; /* Reference duration of an interval */
+ double duration_ref = -1; /* Reference duration of an interval */
res_T res = RES_OK;
ASSERT(smeteo && name);
@@ -348,40 +395,33 @@ load_stream(struct smeteo* smeteo, FILE* fp, const char* name)
if((res = parse_line(smeteo, txtrdr)) != RES_OK) goto error;
- #define COMPUTE_TIME_INTERVAL(Id) \
-
if(i == 0) {
/* Calculate the reference of the interval duration.
*
* The dates of the intervals are relative to midnight on January 1, 1850.
* In addition, their time is defined at the center of the interval. Thus,
* for the first interval, calculate its duration by multiplying its date
- * relative to January 1, 1850 by 2. This will be the reference duration
- * for the intervals */
- interval_ref = darray_entry_cdata_get(&smeteo->entries)[i].day_1850 * 2;
+ * relative to January 1, 1850 by 2. This will be the reference duration*/
+ duration_ref = darray_entry_cdata_get(&smeteo->entries)[i].day_1850 * 2;
} else {
- /* Check that the interval duration is constant */
- const double interval =
- darray_entry_cdata_get(&smeteo->entries)[i-0].day_1850
- - darray_entry_cdata_get(&smeteo->entries)[i-1].day_1850;
- const double eps = interval_ref*1e-6;
-
- if(!eq_eps(interval, interval_ref, eps)) {
- ERROR(smeteo,
- "%s:%lu: invalid time interval. "
- "It is calculated from the `day_1850' variables between consecutive "
- "intervals. The interval duration must be constant, which is not the "
- "case here. Reference interval: %g; current interval: %g -- "
- "%g != %g +/- %g.\n",
- txtrdr_get_name(txtrdr), txtrdr_get_line_num(txtrdr),
- interval_ref, interval, interval_ref, interval, eps);
- res = RES_BAD_ARG;
- goto error;
- }
+ res = check_interval_duration(smeteo, txtrdr, i, duration_ref);
+ if(res != RES_OK) goto error;
+
+ /* Note that although this is a constraint of the smeteo file format, it
+ * is not actually necessary to check that the intervals are sorted in
+ * ascending order. Checking the duration of the interval will also reveal
+ * an invalid order, as the duration would be negative when calculated
+ * from the temporal center of two consecutive intervals. Unless the
+ * day_1850 variables are invalid in relation to the date of the
+ * intervals. But in this situation, checking the order would also give a
+ * false positive. Not to mention that the correspondence between the date
+ * and the value day_1850 should then be verified. However, this would be
+ * difficult to achieve, as converting a date to the "day_1850" format
+ * seems complicated given all the special cases related to time
+ * conversion (leap years, leap seconds). It would be interesting to study
+ * how this is done by the user who generates the smeteo files. */
}
-
- #undef COMPUTE_TIME_INTERVAL
}
exit: