core: introduce a few user-defined literals for unit types

Thise makes initialization of unit types more palatable.

For example:

    surface.time = sample.time - duration_t { .seconds = 20 };
=>  surface.time = sample.time - 20_sec;

    delta_depth.mm = feet_to_mm(1.0); // 1ft
=>  delta_depth = 1_ft;

    get_cylinderid_at_time(..., { .seconds = 20 * 60 + 1 }));
=>  get_cylinderid_at_time(..., 20_min + 1_sec));

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2024-09-03 17:04:48 +02:00 committed by bstoeger
parent f09601bc93
commit ae81b42fe2
36 changed files with 320 additions and 264 deletions

View file

@ -677,7 +677,7 @@ static void cochran_parse_dive(const unsigned char *decode, unsigned mod,
cylinder_t cyl = default_cylinder(dive.get());
cyl.gasmix.o2.permille = (log[CMD_O2_PERCENT] / 256
+ log[CMD_O2_PERCENT + 1]) * 10;
cyl.gasmix.he.permille = 0;
cyl.gasmix.he = 0_percent;
dive->cylinders.add(0, std::move(cyl));
} else {
dc->model = "Commander";
@ -686,7 +686,7 @@ static void cochran_parse_dive(const unsigned char *decode, unsigned mod,
cylinder_t cyl = default_cylinder(dive.get());
cyl.gasmix.o2.permille = (log[CMD_O2_PERCENT + g * 2] / 256
+ log[CMD_O2_PERCENT + g * 2 + 1]) * 10;
cyl.gasmix.he.permille = 0;
cyl.gasmix.he = 0_percent;
dive->cylinders.add(g, std::move(cyl));
}
}

View file

@ -239,19 +239,19 @@ static char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, struct
read_bytes(1);
switch (tmp_1byte) {
case 1:
dt_dive->dcs[0].surface_pressure.mbar = 1013;
dt_dive->dcs[0].surface_pressure = 1_atm;
break;
case 2:
dt_dive->dcs[0].surface_pressure.mbar = 932;
dt_dive->dcs[0].surface_pressure = 932_mbar;
break;
case 3:
dt_dive->dcs[0].surface_pressure.mbar = 828;
dt_dive->dcs[0].surface_pressure = 828_mbar;
break;
case 4:
dt_dive->dcs[0].surface_pressure.mbar = 735;
dt_dive->dcs[0].surface_pressure = 735_mbar;
break;
default:
dt_dive->dcs[0].surface_pressure.mbar = 1013;
dt_dive->dcs[0].surface_pressure = 1_atm;
}
/*
@ -336,9 +336,9 @@ static char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, struct
cylinder_t cyl;
cyl.type.size.mliter = tmp_2bytes * 10;
cyl.type.description = cyl_type_by_size(tmp_2bytes * 10);
cyl.start.mbar = 200000;
cyl.gasmix.he.permille = 0;
cyl.gasmix.o2.permille = 210;
cyl.start = 200_bar;
cyl.gasmix.he = 0_percent;
cyl.gasmix.o2 = 21_percent;
cyl.manually_added = true;
dt_dive->cylinders.push_back(std::move(cyl));
}
@ -365,7 +365,7 @@ static char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, struct
if (tmp_2bytes != 0x7fff)
dt_dive->watertemp.mkelvin = dt_dive->dcs[0].watertemp.mkelvin = C_to_mkelvin((double)(tmp_2bytes / 100));
else
dt_dive->watertemp.mkelvin = 0;
dt_dive->watertemp = 0_K;
/*
* Air used in bar*100.

View file

@ -495,8 +495,8 @@ void clear_vpmb_state(struct deco_state *ds)
ds->max_he_crushing_pressure[ci] = 0.0;
}
ds->max_ambient_pressure = 0;
ds->first_ceiling_pressure.mbar = 0;
ds->max_bottom_ceiling_pressure.mbar = 0;
ds->first_ceiling_pressure = 0_bar;
ds->max_bottom_ceiling_pressure = 0_bar;
}
void clear_deco(struct deco_state *ds, double surface_pressure, bool in_planner)

View file

@ -498,7 +498,7 @@ void update_setpoint_events(const struct dive *dive, struct divecomputer *dc)
struct gasmix gasmix = loop.at(sample.time.seconds).first;
gas_pressures pressures = fill_pressures(lrint(calculate_depth_to_mbarf(sample.depth.mm, dc->surface_pressure, 0)), gasmix ,0, dc->divemode);
if (abs(sample.setpoint.mbar - (int)(1000 * pressures.o2)) <= 50)
sample.setpoint.mbar = 0;
sample.setpoint = 0_baro2;
}
}
@ -809,7 +809,7 @@ static void fixup_dc_temp(struct dive &dive, struct divecomputer &dc)
* the redundant ones.
*/
if (lasttemp == temp)
sample.temperature.mkelvin = 0;
sample.temperature = 0_K;
else
lasttemp = temp;
@ -839,7 +839,7 @@ static void simplify_dc_pressures(struct divecomputer &dc)
if (index == lastindex[j]) {
/* Remove duplicate redundant pressure information */
if (pressure == lastpressure[j])
sample.pressure[j].mbar = 0;
sample.pressure[j] = 0_bar;
}
lastindex[j] = index;
lastpressure[j] = pressure;
@ -912,7 +912,7 @@ static bool validate_gaschange(struct dive &dive, struct event &event)
/* We'll get rid of the per-event gasmix, but for now sanitize it */
if (gasmix_is_air(event.gas.mix))
event.gas.mix.o2.permille = 0;
event.gas.mix.o2 = 0_percent;
/* Do we already have a cylinder index for this gasmix? */
if (event.gas.index >= 0)
@ -993,7 +993,7 @@ static void fixup_dc_sample_sensors(struct dive &dive, struct divecomputer &dc)
// No invalid sensor ID's, please
if (sensor < 0 || sensor > MAX_SENSORS) {
sample.sensor[j] = NO_SENSOR;
sample.pressure[j].mbar = 0;
sample.pressure[j] = 0_bar;
continue;
}
@ -1076,9 +1076,9 @@ void dive::fixup_no_cylinder()
for (auto &cyl: cylinders) {
add_cylinder_description(cyl.type);
if (same_rounded_pressure(cyl.sample_start, cyl.start))
cyl.start.mbar = 0;
cyl.start = 0_bar;
if (same_rounded_pressure(cyl.sample_end, cyl.end))
cyl.end.mbar = 0;
cyl.end = 0_bar;
}
for (auto &ws: weightsystems)
@ -1120,7 +1120,7 @@ static void merge_one_sample(const struct sample &sample, struct divecomputer &d
append_sample(surface, &dc);
surface.time = sample.time - duration_t { .seconds = 20 };
surface.time = sample.time - 20_sec;
append_sample(surface, &dc);
}
}
@ -1399,7 +1399,7 @@ static void sample_renumber(struct sample &s, const struct sample *prev, const i
// Remove sensor and gas pressure info
if (!prev) {
s.sensor[j] = 0;
s.pressure[j].mbar = 0;
s.pressure[j] = 0_bar;
} else {
s.sensor[j] = prev->sensor[j];
s.pressure[j] = prev->pressure[j];
@ -2331,8 +2331,9 @@ fraction_t dive::best_o2(depth_t depth, bool in_planner) const
fo2.permille = (po2 * 100 / depth_to_mbar(depth.mm)) * 10; //use integer arithmetic to round down to nearest percent
// Don't permit >100% O2
// TODO: use std::min, once we have comparison
if (fo2.permille > 1000)
fo2.permille = 1000;
fo2 = 100_percent;
return fo2;
}
@ -2348,8 +2349,9 @@ fraction_t dive::best_he(depth_t depth, bool o2narcotic, fraction_t fo2) const
} else {
fhe.permille = 1000 - fo2.permille - N2_IN_AIR * pnarcotic / ambient;
}
// TODO: use std::max, once we have comparison
if (fhe.permille < 0)
fhe.permille = 0;
fhe = 0_percent;
return fhe;
}

View file

@ -118,9 +118,9 @@ static void fill_samples_no_avg(std::vector<sample> &s, int max_d, int max_t, do
s[2].time.seconds = max_t - lrint(max_d / slope) - 180;
s[2].depth.mm = max_d;
s[3].time.seconds = max_t - lrint(5000 / slope) - 180;
s[3].depth.mm = 5000;
s[3].depth = 5_m;
s[4].time.seconds = max_t - lrint(5000 / slope);
s[4].depth.mm = 5000;
s[4].depth = 5_m;
}
}

View file

@ -51,18 +51,18 @@ void dive_table::force_fixup_dive(struct dive &d) const
duration_t old_duration = d.duration;
std::vector<start_end_pressure> old_pressures(d.cylinders.size());
d.maxdepth.mm = 0;
dc->maxdepth.mm = 0;
d.watertemp.mkelvin = 0;
dc->watertemp.mkelvin = 0;
d.duration.seconds = 0;
d.maxtemp.mkelvin = 0;
d.mintemp.mkelvin = 0;
d.maxdepth = 0_m;
dc->maxdepth = 0_m;
d.watertemp = 0_K;
dc->watertemp = 0_K;
d.duration = 0_sec;
d.maxtemp = 0_K;
d.mintemp = 0_K;
for (auto [i, cyl]: enumerated_range(d.cylinders)) {
old_pressures[i].start = cyl.start;
old_pressures[i].end = cyl.end;
cyl.start.mbar = 0;
cyl.end.mbar = 0;
cyl.start = 0_bar;
cyl.end = 0_bar;
}
fixup_dive(d);
@ -95,7 +95,7 @@ std::unique_ptr<dive> dive_table::default_dive()
{
auto d = std::make_unique<dive>();
d->when = time(nullptr) + gettimezoneoffset() + 3600;
d->dcs[0].duration.seconds = 40 * 60;
d->dcs[0].duration = 40_min;
d->dcs[0].maxdepth.mm = M_OR_FT(15, 45);
d->dcs[0].meandepth.mm = M_OR_FT(13, 39); // this creates a resonable looking safety stop
make_manually_added_dive_dc(&d->dcs[0]);

View file

@ -80,7 +80,7 @@ static void exportHTMLstatistics(const QString filename, struct htmlExportSettin
stats_summary stats = calculate_stats_summary(hes.selectedOnly);
total_stats.selection_size = 0;
total_stats.total_time.seconds = 0;
total_stats.total_time = 0_sec;
out << "divestat=[";
if (hes.yearlyStatistics) {

View file

@ -317,8 +317,8 @@ void reset_cylinders(struct dive *dive, bool track_gas)
cyl.depth = dive->gas_mod(cyl.gasmix, decopo2, M_OR_FT(3,10));
if (track_gas)
cyl.start.mbar = cyl.end.mbar = cyl.type.workingpressure.mbar;
cyl.gas_used.mliter = 0;
cyl.deco_gas_used.mliter = 0;
cyl.gas_used = 0_l;
cyl.deco_gas_used = 0_l;
}
}
@ -404,8 +404,8 @@ void add_default_cylinder(struct dive *d)
} else {
// roughly an AL80
cyl.type.description = translate("gettextFromC", "unknown");
cyl.type.size.mliter = 11100;
cyl.type.workingpressure.mbar = 207000;
cyl.type.size = 11100_ml;
cyl.type.workingpressure = 207_bar;
}
d->cylinders.add(0, std::move(cyl));
reset_cylinders(d, false);

View file

@ -54,7 +54,7 @@ void sanitize_gasmix(struct gasmix &mix)
return;
/* 20.8% to 21% O2 is just air */
if (gasmix_is_air(mix)) {
mix.o2.permille = 0;
mix.o2 = 0_percent;
return;
}
}

View file

@ -17,7 +17,7 @@ struct gasmix {
std::string name() const;
};
static const struct gasmix gasmix_invalid = { { .permille = -1 }, { .permille = -1 } };
static const struct gasmix gasmix_air = { { .permille = 0 }, { .permille = 0 } };
static const struct gasmix gasmix_air = { 0_percent, 0_percent };
enum gastype {
GASTYPE_AIR,

View file

@ -519,10 +519,10 @@ int parse_txt_file(const char *filename, const char *csv, struct divelog *log)
{
cylinder_t cyl;
cyl.cylinder_use = OXYGEN;
cyl.type.size.mliter = 3000;
cyl.type.workingpressure.mbar = 200000;
cyl.type.size = 3_l;
cyl.type.workingpressure = 200_bar;
cyl.type.description = "3l Mk6";
cyl.gasmix.o2.permille = 1000;
cyl.gasmix.o2 = 100_percent;
cyl.manually_added = true;
cyl.bestmix_o2 = 0;
cyl.bestmix_he = 0;
@ -532,8 +532,8 @@ int parse_txt_file(const char *filename, const char *csv, struct divelog *log)
{
cylinder_t cyl;
cyl.cylinder_use = DILUENT;
cyl.type.size.mliter = 3000;
cyl.type.workingpressure.mbar = 200000;
cyl.type.size = 3_l;
cyl.type.workingpressure = 200_bar;
cyl.type.description = "3l Mk6";
value = parse_mkvi_value(memtxt.data(), "Helium percentage");
he = atoi(value.c_str());

View file

@ -171,7 +171,7 @@ static int divinglog_profile(void *param, int, char **data, char **)
*/
int val = atoi_n(ptr4, 3);
if (state->cur_sample->in_deco) {
state->cur_sample->ndl.seconds = 0;
state->cur_sample->ndl = 0_sec;
if (val)
state->cur_sample->tts.seconds = val * 60;
} else {

View file

@ -316,7 +316,7 @@ static int dm5_cylinders(void *param, int, char **data, char **)
* value is 0 (and using metric units). So we just use
* the same 12 liters when size is not available */
if (permissive_strtod(data[6], NULL) == 0.0 && cyl->start.mbar)
cyl->type.size.mliter = 12000;
cyl->type.size = 12_l;
else
cyl->type.size.mliter = lrint((permissive_strtod(data[6], NULL)) * 1000);
}

View file

@ -160,7 +160,7 @@ static dc_status_t parse_gasmixes(device_data_t *devdata, struct dive *dive, dc_
}
}
bool no_volume = true;
struct gasmix bottom_gas = { { .permille = 1000}, {} }; /* Default to pure O2, or air if there are no mixes defined */
struct gasmix bottom_gas = { 100_percent, 0_percent }; /* Default to pure O2, or air if there are no mixes defined */
if (ngases == 0) {
bottom_gas = gasmix_air;
}
@ -291,7 +291,7 @@ static dc_status_t parse_gasmixes(device_data_t *devdata, struct dive *dive, dc_
cyl.end.mbar = lrint(tank.endpressure * 1000);
} else if (devdata->vendor == "Uwatec") {
cyl.start.mbar = lrint(tank.beginpressure * 1000 + 30000);
cyl.end.mbar = 30000;
cyl.end = 30_bar;
}
}
}
@ -850,7 +850,7 @@ static int dive_cb(const unsigned char *data, unsigned int size,
/* Various libdivecomputer interface fixups */
if (dive->dcs[0].airtemp.mkelvin == 0 && first_temp_is_air && !dive->dcs[0].samples.empty()) {
dive->dcs[0].airtemp = dive->dcs[0].samples[0].temperature;
dive->dcs[0].samples[0].temperature.mkelvin = 0;
dive->dcs[0].samples[0].temperature = 0_K;
}
/* special case for bug in Tecdiving DiveComputer.eu

View file

@ -667,8 +667,8 @@ static struct sample *new_sample(struct git_parser_state *state)
size_t num_samples = state->active_dc->samples.size();
if (num_samples >= 2) {
*sample = state->active_dc->samples[num_samples - 2];
sample->pressure[0].mbar = 0;
sample->pressure[1].mbar = 0;
sample->pressure[0] = 0_bar;
sample->pressure[1] = 0_bar;
} else {
sample->sensor[0] = sanitize_sensor_id(state->active_dive.get(), !state->o2pressure_sensor);
sample->sensor[1] = sanitize_sensor_id(state->active_dive.get(), state->o2pressure_sensor);

View file

@ -531,7 +531,7 @@ static bool parseASF(QFile &f, metadata *metadata)
mediatype_t get_metadata(const char *filename_in, metadata *data)
{
data->timestamp = 0;
data->duration.seconds = 0;
data->duration = 0_sec;
data->location.lat.udeg = 0;
data->location.lon.udeg = 0;

View file

@ -328,7 +328,7 @@ static void temperature(const char *buffer, temperature_t *temperature, struct p
/* temperatures outside -40C .. +70C should be ignored */
if (temperature->mkelvin < ZERO_C_IN_MKELVIN - 40000 ||
temperature->mkelvin > ZERO_C_IN_MKELVIN + 70000)
temperature->mkelvin = 0;
*temperature = 0_K;
}
static void sampletime(const char *buffer, duration_t *time)
@ -351,7 +351,7 @@ static void sampletime(const char *buffer, duration_t *time)
time->seconds = (hr * 60 + min) * 60 + sec;
break;
default:
time->seconds = 0;
*time = 0_sec;
report_info("Strange sample time reading %s", buffer);
}
}
@ -715,7 +715,7 @@ static void parse_libdc_deco(const char *buffer, struct sample *s)
s->in_deco = false;
// The time wasn't stoptime, it was ndl
s->ndl = s->stoptime;
s->stoptime.seconds = 0;
s->stoptime = 0_sec;
}
}

View file

@ -267,8 +267,7 @@ void dive_end(struct parser_state *state)
}
state->cur_dive.reset();
state->cur_dc = NULL;
state->cur_location.lat.udeg = 0;
state->cur_location.lon.udeg = 0;
state->cur_location = location_t();
}
void trip_start(struct parser_state *state)
@ -350,8 +349,8 @@ void sample_start(struct parser_state *state)
if (dc->samples.size() > 1) {
*sample = dc->samples[dc->samples.size() - 2];
sample->pressure[0].mbar = 0;
sample->pressure[1].mbar = 0;
sample->pressure[0] = 0_bar;
sample->pressure[1] = 0_bar;
} else {
sample->sensor[0] = sanitize_sensor_id(state->cur_dive.get(), !state->o2pressure_sensor);
sample->sensor[1] = sanitize_sensor_id(state->cur_dive.get(), state->o2pressure_sensor);

View file

@ -201,7 +201,7 @@ static void create_dive_from_plan(struct diveplan &diveplan, struct dive *dive,
cylinder_t *cyl;
int oldpo2 = 0;
int lasttime = 0, last_manual_point = 0;
depth_t lastdepth = {.mm = 0};
depth_t lastdepth;
int lastcylid;
enum divemode_t type = dc->divemode;
@ -305,7 +305,7 @@ divedatapoint::divedatapoint(int time_incr, int depth, int cylinderid, int po2,
time(time_incr),
depth{ .mm = depth },
cylinderid(cylinderid),
minimum_gas{ .mbar = 0 },
minimum_gas = 0_bar;
setpoint(po2),
entered(entered),
divemode(OC)
@ -654,7 +654,7 @@ std::vector<decostop> plan(struct deco_state *ds, struct diveplan &diveplan, str
}
clear_deco(ds, dive->surface_pressure.mbar / 1000.0, true);
ds->max_bottom_ceiling_pressure.mbar = ds->first_ceiling_pressure.mbar = 0;
ds->max_bottom_ceiling_pressure = ds->first_ceiling_pressure = 0_bar;
create_dive_from_plan(diveplan, dive, dc, is_planner);
// Do we want deco stop array in metres or feet?

View file

@ -41,7 +41,7 @@ preferences::preferences() :
ascratestops(9000 / 60),
ascrate50(9000 / 60),
ascrate75(9000 / 60),
bestmixend({ .mm = 30'000 }),
bestmixend(30_m),
bottompo2(1400),
bottomsac(20000),
decopo2(1600),

View file

@ -209,7 +209,6 @@ static void check_setpoint_events(const struct dive *, const struct divecomputer
{
size_t i = 0;
pressure_t setpoint;
setpoint.mbar = 0;
event_loop loop("SP change", *dc);
bool found = false;
@ -848,7 +847,7 @@ static void calculate_deco_information(struct deco_state *ds, const struct deco_
if (!in_planner) {
ds->deco_time = 0;
ds->first_ceiling_pressure.mbar = 0;
ds->first_ceiling_pressure = 0_bar;
} else {
ds->deco_time = planner_ds->deco_time;
ds->first_ceiling_pressure = planner_ds->first_ceiling_pressure;
@ -1179,7 +1178,7 @@ static void fill_o2_values(const struct dive *dive, const struct divecomputer *d
o2pressure.mbar = calculate_ccr_po2(entry, dc); // ...calculate the po2 based on the sensor data
entry.o2pressure.mbar = std::min(o2pressure.mbar, amb_pressure.mbar);
} else {
entry.o2pressure.mbar = 0; // initialise po2 to zero for dctype = OC
entry.o2pressure = 0_bar; // initialise po2 to zero for dctype = OC
}
}
}

View file

@ -1293,10 +1293,11 @@ fraction_t string_to_fraction(const char *str)
/*
* Don't permit values less than zero or greater than 100%
*/
// TODO: use std::clamp() once we have comparison on unit types
if (fraction.permille < 0)
fraction.permille = 0;
fraction = 0_percent;
else if (fraction.permille > 1000)
fraction.permille = 1000;
fraction = 100_percent;
return fraction;
}

View file

@ -21,7 +21,7 @@
static void process_temperatures(const struct dive &dp, stats_t &stats)
{
temperature_t min_temp, mean_temp, max_temp = {.mkelvin = 0};
temperature_t min_temp, mean_temp, max_temp;
max_temp.mkelvin = dp.maxtemp.mkelvin;
if (max_temp.mkelvin && (!stats.max_temp.mkelvin || max_temp.mkelvin > stats.max_temp.mkelvin))
@ -262,7 +262,7 @@ std::vector<volume_t> get_gas_used(struct dive *dive)
if (end.mbar && start.mbar > end.mbar)
gases[idx] = cyl.gas_volume(start) - cyl.gas_volume(end);
else
gases[idx].mliter = 0;
gases[idx] = 0_l;
}
return gases;
@ -277,7 +277,7 @@ static std::pair<volume_t, volume_t> get_gas_parts(struct gasmix mix, volume_t v
volume_t air { .mliter = int_cast<int>(((double)vol.mliter * get_n2(mix)) / (1000 - o2_in_topup)) };
volume_t he { .mliter = int_cast<int>(((double)vol.mliter * get_he(mix)) / 1000.0) };
volume_t o2 { .mliter = vol.mliter - he.mliter - air.mliter };
volume_t o2 = vol - he - air;
return std::make_pair(o2, he);
}

View file

@ -254,7 +254,7 @@ void uemis::event(struct dive *dive, struct divecomputer *dc, struct sample *sam
sample->in_deco = true;
sample->stopdepth.mm = stopdepth;
sample->stoptime.seconds = u_sample->hold_time * 60;
sample->ndl.seconds = 0;
sample->ndl = 0_sec;
} else if (flags[0] & 128) {
/* safety stop - distinguished from deco stop by having
* both ndl and stop information */
@ -266,8 +266,8 @@ void uemis::event(struct dive *dive, struct divecomputer *dc, struct sample *sam
/* NDL */
sample->in_deco = false;
lastndl = sample->ndl.seconds = u_sample->hold_time * 60;
sample->stopdepth.mm = 0;
sample->stoptime.seconds = 0;
sample->stopdepth = 0_m;
sample->stoptime = 0_sec;
}
#if UEMIS_DEBUG & 32
printf("%dm:%ds: p_amb_tol:%d surface:%d holdtime:%d holddepth:%d/%d ---> stopdepth:%d stoptime:%d ndl:%d\n",
@ -326,9 +326,9 @@ void uemis::parse_divelog_binary(std::string_view base64, struct dive *dive)
*/
cylinder_t *cyl = dive->get_or_create_cylinder(i);
cyl->type.size.mliter = lrintf(volume);
cyl->type.workingpressure.mbar = 202600;
cyl->type.workingpressure = 202600_mbar;
cyl->gasmix.o2.permille = *(uint8_t *)(data.data() + 120 + 25 * (gasoffset + i)) * 10;
cyl->gasmix.he.permille = 0;
cyl->gasmix.he = 0_percent;
}
/* first byte of divelog data is at offset 0x123 */
size_t i = 0x123;
@ -353,7 +353,7 @@ void uemis::parse_divelog_binary(std::string_view base64, struct dive *dive)
u_sample++;
}
if (sample)
dive->dcs[0].duration = sample->time - duration_t { .seconds = 1 };
dive->dcs[0].duration = sample->time - 1_sec;
/* get data from the footer */
add_extra_data(dc, "FW Version",

View file

@ -120,6 +120,14 @@ struct duration_t : public unit_base<duration_t>
{
int32_t seconds = 0; // durations up to 34 yrs
};
static inline duration_t operator""_sec(unsigned long long sec)
{
return { .seconds = static_cast<int32_t>(sec) };
}
static inline duration_t operator""_min(unsigned long long min)
{
return { .seconds = static_cast<int32_t>(min * 60) };
}
struct offset_t : public unit_base<offset_t>
{
@ -130,16 +138,44 @@ struct depth_t : public unit_base<depth_t> // depth to 2000 km
{
int32_t mm = 0;
};
static inline depth_t operator""_mm(unsigned long long mm)
{
return { .mm = static_cast<int32_t>(mm) };
}
static inline depth_t operator""_m(unsigned long long m)
{
return { .mm = static_cast<int32_t>(m * 1000) };
}
static inline depth_t operator""_ft(unsigned long long ft)
{
return { .mm = static_cast<int32_t>(round(ft * 304.8)) };
}
struct pressure_t : public unit_base<pressure_t>
{
int32_t mbar = 0; // pressure up to 2000 bar
};
static inline pressure_t operator""_mbar(unsigned long long mbar)
{
return { .mbar = static_cast<int32_t>(mbar) };
}
static inline pressure_t operator""_bar(unsigned long long bar)
{
return { .mbar = static_cast<int32_t>(bar * 1000) };
}
static inline pressure_t operator""_atm(unsigned long long atm)
{
return { .mbar = static_cast<int32_t>(round(atm * 1013.25)) };
}
struct o2pressure_t : public unit_base<o2pressure_t>
{
uint16_t mbar = 0;
};
static inline o2pressure_t operator""_baro2(unsigned long long bar)
{
return { .mbar = static_cast<uint16_t>(bar * 1000) };
}
struct bearing_t : public unit_base<bearing_t>
{
@ -150,6 +186,10 @@ struct temperature_t : public unit_base<temperature_t>
{
uint32_t mkelvin = 0; // up to 4 MK (temperatures in K are always positive)
};
static inline temperature_t operator""_K(unsigned long long K)
{
return { .mkelvin = static_cast<uint32_t>(K * 1000) };
}
struct temperature_sum_t : public unit_base<temperature_sum_t>
{
@ -160,11 +200,27 @@ struct volume_t : public unit_base<volume_t>
{
int mliter = 0;
};
static inline volume_t operator""_ml(unsigned long long ml)
{
return { .mliter = static_cast<int>(ml) };
}
static inline volume_t operator""_l(unsigned long long l)
{
return { .mliter = static_cast<int>(l * 1000) };
}
struct fraction_t : public unit_base<fraction_t>
{
int permille = 0;
};
static inline fraction_t operator""_permille(unsigned long long permille)
{
return { .permille = static_cast<int>(permille) };
}
static inline fraction_t operator""_percent(unsigned long long percent)
{
return { .permille = static_cast<int>(percent * 10) };
}
struct weight_t : public unit_base<weight_t>
{