core: implement interpolate() function for unit types

Calls the global interpolate() function for integer types.

For now, the template is enabled if the arguments are not
integer types. Might want to refine that in the future.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2024-12-14 09:49:31 +01:00 committed by Michael Keller
parent 1ccfb823f0
commit 0e77dd9a68
4 changed files with 22 additions and 4 deletions

View file

@ -432,7 +432,7 @@ static void add_dive_to_deco(struct deco_state *ds, const struct dive &dive, boo
int j; int j;
for (j = t0; j < t1; j++) { for (j = t0; j < t1; j++) {
depth_t depth = { .mm = interpolate(psample.depth.mm, sample.depth.mm, j - t0, t1 - t0) }; depth_t depth = interpolate(psample.depth, sample.depth, j - t0, t1 - t0);
auto gasmix = loop.at(j).first; auto gasmix = loop.at(j).first;
add_segment(ds, dive.depth_to_bar(depth), gasmix, 1, sample.setpoint.mbar, add_segment(ds, dive.depth_to_bar(depth), gasmix, 1, sample.setpoint.mbar,
loop_d.at(j), dive.sac, loop_d.at(j), dive.sac,

View file

@ -104,7 +104,7 @@ static void interpolate_transition(struct deco_state *ds, struct dive *dive, dur
int32_t j; int32_t j;
for (j = t0.seconds; j < t1.seconds; j++) { for (j = t0.seconds; j < t1.seconds; j++) {
depth_t depth = depth_t { .mm = interpolate(d0.mm, d1.mm, j - t0.seconds, t1.seconds - t0.seconds) }; depth_t depth = interpolate(d0, d1, j - t0.seconds, t1.seconds - t0.seconds);
add_segment(ds, dive->depth_to_bar(depth), gasmix, 1, po2.mbar, divemode, prefs.bottomsac, true); add_segment(ds, dive->depth_to_bar(depth), gasmix, 1, po2.mbar, divemode, prefs.bottomsac, true);
} }
if (d1.mm > d0.mm) if (d1.mm > d0.mm)

View file

@ -876,6 +876,7 @@ static void calculate_deco_information(struct deco_state *ds, const struct deco_
int time_stepsize = 20; int time_stepsize = 20;
depth_t max_ceiling; depth_t max_ceiling;
depth_t depth { .mm = entry.depth }; depth_t depth { .mm = entry.depth };
depth_t prev_depth { .mm = prev.depth };
divemode_t current_divemode = loop_d.at(entry.sec); divemode_t current_divemode = loop_d.at(entry.sec);
struct gasmix gasmix = loop.at(t1).first; struct gasmix gasmix = loop.at(t1).first;
@ -888,7 +889,7 @@ static void calculate_deco_information(struct deco_state *ds, const struct deco_
if (t0 != t1 && t1 - t0 < time_stepsize) if (t0 != t1 && t1 - t0 < time_stepsize)
time_stepsize = t1 - t0; time_stepsize = t1 - t0;
for (int j = t0 + time_stepsize; j <= t1; j += time_stepsize) { for (int j = t0 + time_stepsize; j <= t1; j += time_stepsize) {
depth_t new_depth { .mm = interpolate(prev.depth, depth.mm, j - t0, t1 - t0) }; depth_t new_depth = interpolate(prev_depth, depth, j - t0, t1 - t0);
add_segment(ds, dive->depth_to_bar(new_depth), add_segment(ds, dive->depth_to_bar(new_depth),
gasmix, time_stepsize, entry.o2pressure.mbar, current_divemode, entry.sac, in_planner); gasmix, time_stepsize, entry.o2pressure.mbar, current_divemode, entry.sac, in_planner);
entry.icd_warning = ds->icd_warning; entry.icd_warning = ds->icd_warning;
@ -915,7 +916,7 @@ static void calculate_deco_information(struct deco_state *ds, const struct deco_
/* If using VPM-B, take first_ceiling_pressure as the deepest ceiling */ /* If using VPM-B, take first_ceiling_pressure as the deepest ceiling */
if (decoMode(in_planner) == VPMB) { if (decoMode(in_planner) == VPMB) {
if (current_ceiling.mm >= first_ceiling.mm || if (current_ceiling.mm >= first_ceiling.mm ||
(time_deep_ceiling == t0 && depth.mm == prev.depth)) { (time_deep_ceiling == t0 && depth.mm == prev_depth.mm)) {
time_deep_ceiling = t1; time_deep_ceiling = t1;
first_ceiling = current_ceiling; first_ceiling = current_ceiling;
ds->first_ceiling_pressure.mbar = dive->depth_to_mbar(first_ceiling); ds->first_ceiling_pressure.mbar = dive->depth_to_mbar(first_ceiling);

View file

@ -2,6 +2,8 @@
#ifndef UNITS_H #ifndef UNITS_H
#define UNITS_H #define UNITS_H
#include "interpolate.h"
#include <math.h> #include <math.h>
#ifndef M_PI #ifndef M_PI
#define M_PI 3.14159265358979323846 #define M_PI 3.14159265358979323846
@ -86,6 +88,12 @@
* _permille -> fraction_t in * _permille -> fraction_t in
* _percent -> fraction_t in % * _percent -> fraction_t in %
* *
* For now, addition and subtraction of values of the same type
* are supported.
*
* A free standing interpolate() function can be used to interpolate
* between types of the same kind (see also the interpolate.h header).
*
* We don't actually use these all yet, so maybe they'll change, but * We don't actually use these all yet, so maybe they'll change, but
* I made a number of types as guidelines. * I made a number of types as guidelines.
*/ */
@ -140,6 +148,15 @@ struct unit_base {
} }
}; };
template <typename T,
std::enable_if_t<!std::is_integral<T>::value, bool> = true>
T interpolate(T a, T b, int part, int whole)
{
return T::from_base(
interpolate(a.get_base(), b.get_base(), part, whole)
);
}
struct duration_t : public unit_base<duration_t> struct duration_t : public unit_base<duration_t>
{ {
int32_t seconds = 0; // durations up to 34 yrs int32_t seconds = 0; // durations up to 34 yrs