diff options
author | Berthold Stoeger <bstoeger@mail.tuwien.ac.at> | 2019-08-05 23:23:10 +0200 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2019-08-08 16:26:31 -0700 |
commit | ddff68ddaec734449d83c6b056739c5474fb0b49 (patch) | |
tree | 7cdab0e27a875e86d5ddb8bec2fa51ced10eb6ad /core | |
parent | 852239e6de541bfeb28b37ec1677a4d1637a7052 (diff) | |
download | subsurface-ddff68ddaec734449d83c6b056739c5474fb0b49.tar.gz |
Parser: remove global state
The parser had global state in the form of a linear regression
and the "plot_depth" variable. Collect that in the deco_state struct and
pass it down the call-chain. Move out the code to update the
regression data to not bother other callers of tissue_tolerance_calc().
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Signed-off-by: Robert C. Helling <helling@atdotde.de>
Diffstat (limited to 'core')
-rw-r--r-- | core/deco.c | 70 | ||||
-rw-r--r-- | core/deco.h | 11 | ||||
-rw-r--r-- | core/planner.c | 33 |
3 files changed, 60 insertions, 54 deletions
diff --git a/core/deco.c b/core/deco.c index cb8273f41..0dd4051c2 100644 --- a/core/deco.c +++ b/core/deco.c @@ -37,8 +37,6 @@ // was introduced in v4.6.3 this can be set to a value of 1.0 which means no correction. #define subsurface_conservatism_factor 1.0 -extern int plot_depth; - //! Option structure for Buehlmann decompression. struct buehlmann_config { double satmult; //! safety at inert gas accumulation as percentage of effect (more than 100). @@ -157,10 +155,6 @@ static const double vpmb_conservatism_lvls[] = { 1.0, 1.05, 1.12, 1.22, 1.35 }; #define TISSUE_ARRAY_SZ sizeof(ds->tissue_n2_sat) -static int sum1; -static long sumx, sumxx; -static double sumy, sumxy; - static double get_crit_radius_He() { if (vpmb_config.conservatism <= 4) @@ -223,7 +217,6 @@ static double vpmb_tolerated_ambient_pressure(struct deco_state *ds, double refe return ds->tissue_n2_sat[ci] + ds->tissue_he_sat[ci] + vpmb_config.other_gases_pressure - total_gradient; } - double tissue_tolerance_calc(struct deco_state *ds, const struct dive *dive, double pressure) { int ci = -1; @@ -292,23 +285,6 @@ double tissue_tolerance_calc(struct deco_state *ds, const struct dive *dive, dou } // We are doing ok if the gradient was computed within ten centimeters of the ceiling. } while (fabs(ret_tolerance_limit_ambient_pressure - reference_pressure) > 0.01); - - if (plot_depth) { - ++sum1; - sumx += plot_depth; - sumxx += (long)plot_depth * plot_depth; - double n2_gradient, he_gradient, total_gradient; - n2_gradient = update_gradient(ds, depth_to_bar(plot_depth, &displayed_dive), ds->bottom_n2_gradient[ds->ci_pointing_to_guiding_tissue]); - he_gradient = update_gradient(ds, depth_to_bar(plot_depth, &displayed_dive), ds->bottom_he_gradient[ds->ci_pointing_to_guiding_tissue]); - total_gradient = ((n2_gradient * ds->tissue_n2_sat[ds->ci_pointing_to_guiding_tissue]) + (he_gradient * ds->tissue_he_sat[ds->ci_pointing_to_guiding_tissue])) - / (ds->tissue_n2_sat[ds->ci_pointing_to_guiding_tissue] + ds->tissue_he_sat[ds->ci_pointing_to_guiding_tissue]); - - double buehlmann_gradient = (1.0 / ds->buehlmann_inertgas_b[ds->ci_pointing_to_guiding_tissue] - 1.0) * depth_to_bar(plot_depth, &displayed_dive) + ds->buehlmann_inertgas_a[ds->ci_pointing_to_guiding_tissue]; - double gf = (total_gradient - vpmb_config.other_gases_pressure) / buehlmann_gradient; - sumxy += gf * plot_depth; - sumy += gf; - plot_depth = 0; - } } return ret_tolerance_limit_ambient_pressure; } @@ -639,30 +615,50 @@ double get_gf(struct deco_state *ds, double ambpressure_bar, const struct dive * return gf; } -double regressiona() +double regressiona(const struct deco_state *ds) { - if (sum1 > 1) { - double avxy = sumxy / sum1; - double avx = (double)sumx / sum1; - double avy = sumy / sum1; - double avxx = (double) sumxx / sum1; + if (ds->sum1 > 1) { + double avxy = ds->sumxy / ds->sum1; + double avx = (double)ds->sumx / ds->sum1; + double avy = ds->sumy / ds->sum1; + double avxx = (double) ds->sumxx / ds->sum1; return (avxy - avx * avy) / (avxx - avx*avx); } else return 0.0; } -double regressionb() +double regressionb(const struct deco_state *ds) { - if (sum1) - return sumy / sum1 - sumx * regressiona() / sum1; + if (ds->sum1) + return ds->sumy / ds->sum1 - ds->sumx * regressiona(ds) / ds->sum1; else return 0.0; } -void reset_regression() +void reset_regression(struct deco_state *ds) { - sum1 = 0; - sumxx = sumx = 0L; - sumy = sumxy = 0.0; + ds->sum1 = 0; + ds->sumxx = ds->sumx = 0L; + ds->sumy = ds->sumxy = 0.0; +} + +void update_regression(struct deco_state *ds, const struct dive *dive) +{ + if (!ds->plot_depth) + return; + ds->sum1 += 1; + ds->sumx += ds->plot_depth; + ds->sumxx += (long)ds->plot_depth * ds->plot_depth; + double n2_gradient, he_gradient, total_gradient; + n2_gradient = update_gradient(ds, depth_to_bar(ds->plot_depth, dive), ds->bottom_n2_gradient[ds->ci_pointing_to_guiding_tissue]); + he_gradient = update_gradient(ds, depth_to_bar(ds->plot_depth, dive), ds->bottom_he_gradient[ds->ci_pointing_to_guiding_tissue]); + total_gradient = ((n2_gradient * ds->tissue_n2_sat[ds->ci_pointing_to_guiding_tissue]) + (he_gradient * ds->tissue_he_sat[ds->ci_pointing_to_guiding_tissue])) + / (ds->tissue_n2_sat[ds->ci_pointing_to_guiding_tissue] + ds->tissue_he_sat[ds->ci_pointing_to_guiding_tissue]); + + double buehlmann_gradient = (1.0 / ds->buehlmann_inertgas_b[ds->ci_pointing_to_guiding_tissue] - 1.0) * depth_to_bar(ds->plot_depth, dive) + ds->buehlmann_inertgas_a[ds->ci_pointing_to_guiding_tissue]; + double gf = (total_gradient - vpmb_config.other_gases_pressure) / buehlmann_gradient; + ds->sumxy += gf * ds->plot_depth; + ds->sumy += gf; + ds->plot_depth = 0; } diff --git a/core/deco.h b/core/deco.h index 4bdc5840d..29a492c93 100644 --- a/core/deco.h +++ b/core/deco.h @@ -41,6 +41,10 @@ struct deco_state { double gf_low_pressure_this_dive; int deco_time; bool icd_warning; + int sum1; + long sumx, sumxx; + double sumy, sumxy; + int plot_depth; }; extern const double buehlmann_N2_t_halflife[]; @@ -63,9 +67,10 @@ extern void vpmb_start_gradient(struct deco_state *ds); extern void clear_vpmb_state(struct deco_state *ds); extern void add_segment(struct deco_state *ds, double pressure, struct gasmix gasmix, int period_in_seconds, int setpoint, enum divemode_t divemode, int sac); -extern double regressiona(); -extern double regressionb(); -extern void reset_regression(); +extern double regressiona(const struct deco_state *ds); +extern double regressionb(const struct deco_state *ds); +extern void reset_regression(struct deco_state *ds); +extern void update_regression(struct deco_state *ds, const struct dive *dive); #ifdef __cplusplus } diff --git a/core/planner.c b/core/planner.c index 0743a6a52..e2c5cf035 100644 --- a/core/planner.c +++ b/core/planner.c @@ -36,7 +36,6 @@ static int decostoplevels_imperial[] = { 0, 3048, 6096, 9144, 12192, 15240, 1828 325120, 345440, 365760, 386080 }; char *disclaimer; -int plot_depth = 0; #if DEBUG_PLAN void dump_plan(struct diveplan *diveplan) { @@ -557,23 +556,28 @@ static bool trial_ascent(struct deco_state *ds, int wait_time, int trial_depth, add_segment(ds, depth_to_bar(trial_depth, dive), gasmix, wait_time, po2, divemode, prefs.decosac); - if (decoMode() == VPMB && (deco_allowed_depth(tissue_tolerance_calc(ds, dive,depth_to_bar(stoplevel, dive)), - surface_pressure, dive, 1) - > stoplevel)) { - restore_deco_state(trial_cache, ds, false); - free(trial_cache); - return false; + if (decoMode() == VPMB) { + double tolerance_limit = tissue_tolerance_calc(ds, dive, depth_to_bar(stoplevel, dive)); + update_regression(ds, dive); + if (deco_allowed_depth(tolerance_limit, surface_pressure, dive, 1) > stoplevel) { + restore_deco_state(trial_cache, ds, false); + free(trial_cache); + return false; + } } while (trial_depth > stoplevel) { + double tolerance_limit; int deltad = ascent_velocity(trial_depth, avg_depth, bottom_time) * TIMESTEP; if (deltad > trial_depth) /* don't test against depth above surface */ deltad = trial_depth; add_segment(ds, depth_to_bar(trial_depth, dive), gasmix, TIMESTEP, po2, divemode, prefs.decosac); - if (deco_allowed_depth(tissue_tolerance_calc(ds, dive, depth_to_bar(trial_depth, dive)), - surface_pressure, dive, 1) > trial_depth - deltad) { + tolerance_limit = tissue_tolerance_calc(ds, dive, depth_to_bar(trial_depth, dive)); + if (decoMode() == VPMB) + update_regression(ds, dive); + if (deco_allowed_depth(tolerance_limit, surface_pressure, dive, 1) > trial_depth - deltad) { /* We should have stopped */ clear_to_ascend = false; break; @@ -878,7 +882,8 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i first_stop_depth = 0; stopidx = bottom_stopidx; ds->first_ceiling_pressure.mbar = depth_to_mbar( - deco_allowed_depth(tissue_tolerance_calc(ds, dive, depth_to_bar(depth, dive)), diveplan->surface_pressure / 1000.0, dive, 1), + deco_allowed_depth(tissue_tolerance_calc(ds, dive, depth_to_bar(depth, dive)), + diveplan->surface_pressure / 1000.0, dive, 1), dive); if (ds->max_bottom_ceiling_pressure.mbar > ds->first_ceiling_pressure.mbar) ds->first_ceiling_pressure.mbar = ds->max_bottom_ceiling_pressure.mbar; @@ -894,7 +899,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i report_error(translate("gettextFromC", "Can't find gas %s"), gasname(gas)); current_cylinder = 0; } - reset_regression(); + reset_regression(ds); while (1) { /* We will break out when we hit the surface */ do { @@ -918,7 +923,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i depth -= deltad; /* Print VPM-Gradient as gradient factor, this has to be done from within deco.c */ if (decodive) - plot_depth = depth; + ds->plot_depth = depth; } while (depth > 0 && depth > stoplevels[stopidx]); if (depth <= 0) @@ -1089,8 +1094,8 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i plan_add_segment(diveplan, clock - previous_point_time, 0, current_cylinder, po2, false, divemode); if (decoMode() == VPMB) { - diveplan->eff_gfhigh = lrint(100.0 * regressionb()); - diveplan->eff_gflow = lrint(100.0 * (regressiona() * first_stop_depth + regressionb())); + diveplan->eff_gfhigh = lrint(100.0 * regressionb(ds)); + diveplan->eff_gflow = lrint(100.0 * (regressiona(ds) * first_stop_depth + regressionb(ds))); } for (int i = 0; i < MAX_CYLINDERS; i++) |