Skip to content

Commit

Permalink
Round gas depth properly
Browse files Browse the repository at this point in the history
The D in MOD, EAD, END, and EADD stands for "depth" and
as such these should be mm in int rather than double.

The intermediate fn2 and fhe2, however, as intermediate
value should not be rounded to an integer.

The upshot of this is a litle more numerical stability.
It should lead to more stable values in TestProfile
when run on architectures with different floating
point precision.

Signed-off-by: Robert C. Helling <helling@atdotde.de>
  • Loading branch information
atdotde committed Dec 6, 2021
1 parent cbe6d89 commit 9fd531d
Show file tree
Hide file tree
Showing 7 changed files with 31,237 additions and 31,232 deletions.
16 changes: 10 additions & 6 deletions core/dive.c
Expand Up @@ -41,7 +41,7 @@ const char *divemode_text_ui[] = {
// For writing/reading files.
const char *divemode_text[] = {"OC", "CCR", "PSCR", "Freedive"};

static int calculate_depth_to_mbar(int depth, pressure_t surface_pressure, int salinity);
static double calculate_depth_to_mbarf(int depth, pressure_t surface_pressure, int salinity);

/*
* The legacy format for sample pressures has a single pressure
Expand Down Expand Up @@ -657,7 +657,7 @@ void update_setpoint_events(const struct dive *dive, struct divecomputer *dc)
gasmix = get_gasmix_from_event(dive, ev);
next = get_next_event(ev, "gaschange");
}
fill_pressures(&pressures, calculate_depth_to_mbar(dc->sample[i].depth.mm, dc->surface_pressure, 0), gasmix ,0, dc->divemode);
fill_pressures(&pressures, lrint(calculate_depth_to_mbarf(dc->sample[i].depth.mm, dc->surface_pressure, 0)), gasmix ,0, dc->divemode);
if (abs(dc->sample[i].setpoint.mbar - (int)(1000 * pressures.o2)) <= 50)
dc->sample[i].setpoint.mbar = 0;
}
Expand Down Expand Up @@ -3209,7 +3209,7 @@ static double salinity_to_specific_weight(int salinity)
/* Pa = N/m^2 - so we determine the weight (in N) of the mass of 10m
* of water (and use standard salt water at 1.03kg per liter if we don't know salinity)
* and add that to the surface pressure (or to 1013 if that's unknown) */
static int calculate_depth_to_mbar(int depth, pressure_t surface_pressure, int salinity)
static double calculate_depth_to_mbarf(int depth, pressure_t surface_pressure, int salinity)
{
double specific_weight;
int mbar = surface_pressure.mbar;
Expand All @@ -3221,13 +3221,17 @@ static int calculate_depth_to_mbar(int depth, pressure_t surface_pressure, int s
if (salinity < 500)
salinity += FRESHWATER_SALINITY;
specific_weight = salinity_to_specific_weight(salinity);
mbar += lrint(depth * specific_weight);
return mbar;
return mbar + depth * specific_weight;
}

int depth_to_mbar(int depth, const struct dive *dive)
{
return calculate_depth_to_mbar(depth, dive->surface_pressure, dive->salinity);
return lrint(calculate_depth_to_mbarf(depth, dive->surface_pressure, dive->salinity));
}

double depth_to_mbarf(int depth, const struct dive *dive)
{
return calculate_depth_to_mbarf(depth, dive->surface_pressure, dive->salinity);
}

double depth_to_bar(int depth, const struct dive *dive)
Expand Down
1 change: 1 addition & 0 deletions core/dive.h
Expand Up @@ -102,6 +102,7 @@ extern fraction_t best_he(depth_t depth, const struct dive *dive, bool o2narcoti

extern int get_surface_pressure_in_mbar(const struct dive *dive, bool non_null);
extern int depth_to_mbar(int depth, const struct dive *dive);
extern double depth_to_mbarf(int depth, const struct dive *dive);
extern double depth_to_bar(int depth, const struct dive *dive);
extern double depth_to_atm(int depth, const struct dive *dive);
extern int rel_mbar_to_depth(int mbar, const struct dive *dive);
Expand Down
24 changes: 12 additions & 12 deletions core/profile.c
Expand Up @@ -1236,15 +1236,15 @@ static void calculate_gas_information_new(const struct dive *dive, const struct
enum divemode_t current_divemode = UNDEF_COMP_TYPE;

for (i = 1; i < pi->nr; i++) {
int fn2, fhe;
double fn2, fhe;
struct plot_data *entry = pi->entry + i;

gasmix = get_gasmix(dive, dc, entry->sec, &evg, gasmix);
amb_pressure = depth_to_bar(entry->depth, dive);
current_divemode = get_current_divemode(dc, entry->sec, &evd, &current_divemode);
fill_pressures(&entry->pressures, amb_pressure, gasmix, (current_divemode == OC) ? 0.0 : entry->o2pressure.mbar / 1000.0, current_divemode);
fn2 = (int)(1000.0 * entry->pressures.n2 / amb_pressure);
fhe = (int)(1000.0 * entry->pressures.he / amb_pressure);
fn2 = 1000.0 * entry->pressures.n2 / amb_pressure;
fhe = 1000.0 * entry->pressures.he / amb_pressure;
if (dc->divemode == PSCR) { // OC pO2 is calulated for PSCR with or without external PO2 monitoring.
struct gasmix gasmix2 = get_gasmix(dive, dc, entry->sec, &evg, gasmix);
entry->scr_OC_pO2.mbar = (int) depth_to_mbar(entry->depth, dive) * get_o2(gasmix2) / 1000;
Expand All @@ -1255,14 +1255,14 @@ static void calculate_gas_information_new(const struct dive *dive, const struct
* END takes O₂ + N₂ (air) into account ("Narcotic" for trimix dives)
* EAD just uses N₂ ("Air" for nitrox dives) */
pressure_t modpO2 = { .mbar = (int)(prefs.modpO2 * 1000) };
entry->mod = (double)gas_mod(gasmix, modpO2, dive, 1).mm;
entry->end = (entry->depth + 10000) * (1000 - fhe) / 1000.0 - 10000;
entry->ead = (entry->depth + 10000) * fn2 / (double)N2_IN_AIR - 10000;
entry->eadd = (entry->depth + 10000) *
entry->mod = gas_mod(gasmix, modpO2, dive, 1).mm;
entry->end = mbar_to_depth(lrint(depth_to_mbarf(entry->depth, dive) * (1000 - fhe) / 1000.0), dive);
entry->ead = mbar_to_depth(lrint(depth_to_mbarf(entry->depth, dive) * fn2 / (double)N2_IN_AIR), dive);
entry->eadd = mbar_to_depth(lrint(depth_to_mbarf(entry->depth, dive) *
(entry->pressures.o2 / amb_pressure * O2_DENSITY +
entry->pressures.n2 / amb_pressure * N2_DENSITY +
entry->pressures.he / amb_pressure * HE_DENSITY) /
(O2_IN_AIR * O2_DENSITY + N2_IN_AIR * N2_DENSITY) * 1000 - 10000;
(O2_IN_AIR * O2_DENSITY + N2_IN_AIR * N2_DENSITY) * 1000), dive);
entry->density = gas_density(gasmix, depth_to_mbar(entry->depth, dive));
if (entry->mod < 0)
entry->mod = 0;
Expand Down Expand Up @@ -1452,22 +1452,22 @@ static void plot_string(const struct dive *d, const struct plot_info *pi, int id
if (prefs.pp_graphs.phe && entry->pressures.he > 0)
put_format_loc(b, translate("gettextFromC", "pHe: %.2fbar\n"), entry->pressures.he);
if (prefs.mod && entry->mod > 0) {
mod = lrint(get_depth_units(lrint(entry->mod), NULL, &depth_unit));
mod = lrint(get_depth_units(entry->mod, NULL, &depth_unit));
put_format_loc(b, translate("gettextFromC", "MOD: %d%s\n"), mod, depth_unit);
}
eadd = lrint(get_depth_units(lrint(entry->eadd), NULL, &depth_unit));
eadd = lrint(get_depth_units(entry->eadd, NULL, &depth_unit));

if (prefs.ead) {
switch (pi->dive_type) {
case NITROX:
if (entry->ead > 0) {
ead = lrint(get_depth_units(lrint(entry->ead), NULL, &depth_unit));
ead = lrint(get_depth_units(entry->ead, NULL, &depth_unit));
put_format_loc(b, translate("gettextFromC", "EAD: %d%s\nEADD: %d%s / %.1fg/ℓ\n"), ead, depth_unit, eadd, depth_unit, entry->density);
break;
}
case TRIMIX:
if (entry->end > 0) {
end = lrint(get_depth_units(lrint(entry->end), NULL, &depth_unit));
end = lrint(get_depth_units(entry->end, NULL, &depth_unit));
put_format_loc(b, translate("gettextFromC", "END: %d%s\nEADD: %d%s / %.1fg/ℓ\n"), end, depth_unit, eadd, depth_unit, entry->density);
break;
}
Expand Down
2 changes: 1 addition & 1 deletion core/profile.h
Expand Up @@ -58,7 +58,7 @@ struct plot_data {
pressure_t o2sensor[3]; //for rebreathers with up to 3 PO2 sensors
pressure_t o2setpoint;
pressure_t scr_OC_pO2;
double mod, ead, end, eadd;
int mod, ead, end, eadd;
velocity_t velocity;
int speed;
// stats over 9 minute window:
Expand Down
8 changes: 4 additions & 4 deletions core/save-profiledata.c
Expand Up @@ -77,10 +77,10 @@ static void put_pd(struct membuffer *b, const struct plot_info *pi, int idx)
put_int(b, entry->o2sensor[2].mbar);
put_int(b, entry->o2setpoint.mbar);
put_int(b, entry->scr_OC_pO2.mbar);
put_double(b, entry->mod);
put_double(b, entry->ead);
put_double(b, entry->end);
put_double(b, entry->eadd);
put_int(b, entry->mod);
put_int(b, entry->ead);
put_int(b, entry->end);
put_int(b, entry->eadd);
switch (entry->velocity) {
case STABLE:
put_csv_string(b, "STABLE");
Expand Down

0 comments on commit 9fd531d

Please sign in to comment.